Skip to content

Commit

Permalink
refactor: Use functions from limited API
Browse files Browse the repository at this point in the history
Replace unsafe macros and direct struct access with functions from
the subset of limited API functions.

* `PySequence_Fast_GET_ITEM` -> `PySequence_GetItem`
* `PyTuple_SET_ITEM` -> `PyTuple_SetItem`
* `PyList_SET_ITEM` -> `PyList_SetItem`
* `PyUnicode_AsUTF8AndSize` -> `PyUnicode_AsUTF8String` +
  `PyBytes_AsStringAndSize`. The function `PyUnicode_AsUTF8AndSize` is
  not in limited API before Python 3.10.
* `const char *tp_name` -> `Py_TYPE()` string representation

See: python-ldap#540
Signed-off-by: Christian Heimes <cheimes@redhat.com>
  • Loading branch information
tiran committed Nov 3, 2023
1 parent f481010 commit 5d49f27
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 14 deletions.
27 changes: 19 additions & 8 deletions Modules/LDAPObject.c
Original file line number Diff line number Diff line change
Expand Up @@ -280,9 +280,9 @@ attrs_from_List(PyObject *attrlist, char ***attrsp)
}
else {
PyObject *item = NULL;
PyObject *bstr;
Py_ssize_t i, len, strlen;

const char *str;
char *str;

seq = PySequence_Fast(attrlist, "expected list of strings or None");
if (seq == NULL)
Expand All @@ -297,24 +297,35 @@ attrs_from_List(PyObject *attrlist, char ***attrsp)

for (i = 0; i < len; i++) {
attrs[i] = NULL;
item = PySequence_Fast_GET_ITEM(seq, i);
item = PySequence_GetItem(seq, i);
if (item == NULL)
goto error;
if (!PyUnicode_Check(item)) {
LDAPerror_TypeError
("attrs_from_List(): expected string in list", item);
Py_DECREF(item);
goto error;
}
// PyUnicode_AsUTF8AndSize is not in limited API < 3.10.
bstr = PyUnicode_AsUTF8String(item);
Py_DECREF(item);
if (bstr == NULL) {
goto error;
}
if (PyBytes_AsStringAndSize(bstr, &str, &strlen) < 0) {
Py_DECREF(bstr);
goto error;
}
str = PyUnicode_AsUTF8AndSize(item, &strlen);
/* Make a copy. PyBytes_AsString* / PyUnicode_AsUTF8* return
* internal values that must be treated like const char. Python
* 3.7 actually returns a const char.
* internal values that must be treated like const char.
*/
attrs[i] = (char *)PyMem_NEW(char, strlen + 1);

if (attrs[i] == NULL)
if (attrs[i] == NULL) {
Py_DECREF(bstr);
goto nomem;
}
memcpy(attrs[i], str, strlen + 1);
Py_DECREF(bstr);
}
attrs[len] = NULL;
Py_DECREF(seq);
Expand Down
2 changes: 1 addition & 1 deletion Modules/ldapcontrol.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ LDAPControls_to_List(LDAPControl **ldcs)
Py_DECREF(res);
return NULL;
}
PyList_SET_ITEM(res, i, pyctrl);
PyList_SetItem(res, i, pyctrl);
}
return res;
}
Expand Down
10 changes: 5 additions & 5 deletions Modules/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,8 @@ LDAP_set_option(LDAPObject *self, int option, PyObject *value)
/* TypeError: mention either float or None is expected */
PyErr_Clear();
PyErr_Format(PyExc_TypeError,
"A float or None is expected for timeout, got %.100s",
Py_TYPE(value)->tp_name);
"A float or None is expected for timeout, got %S",
Py_TYPE(value));
}
return 0;
}
Expand Down Expand Up @@ -302,9 +302,9 @@ LDAP_get_option(LDAPObject *self, int option)
num_extensions++;
extensions = PyTuple_New(num_extensions);
for (i = 0; i < num_extensions; i++)
PyTuple_SET_ITEM(extensions, i,
PyUnicode_FromString(apiinfo.ldapai_extensions
[i]));
PyTuple_SetItem(extensions, i,
PyUnicode_FromString(apiinfo.ldapai_extensions
[i]));

/* return api info as a dictionary */
v = Py_BuildValue("{s:i, s:i, s:i, s:s, s:i, s:O}",
Expand Down

0 comments on commit 5d49f27

Please sign in to comment.