From 5d49f27fff5705caac090ecf020add16bec260f5 Mon Sep 17 00:00:00 2001 From: Christian Heimes Date: Mon, 30 Oct 2023 10:16:20 +0100 Subject: [PATCH] refactor: Use functions from limited API 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: https://github.com/python-ldap/python-ldap/issues/540 Signed-off-by: Christian Heimes --- Modules/LDAPObject.c | 27 +++++++++++++++++++-------- Modules/ldapcontrol.c | 2 +- Modules/options.c | 10 +++++----- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Modules/LDAPObject.c b/Modules/LDAPObject.c index 71fac73e..54ab2e4b 100644 --- a/Modules/LDAPObject.c +++ b/Modules/LDAPObject.c @@ -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) @@ -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); diff --git a/Modules/ldapcontrol.c b/Modules/ldapcontrol.c index 4a37b614..9fae1056 100644 --- a/Modules/ldapcontrol.c +++ b/Modules/ldapcontrol.c @@ -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; } diff --git a/Modules/options.c b/Modules/options.c index 4577b075..f4e6891f 100644 --- a/Modules/options.c +++ b/Modules/options.c @@ -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; } @@ -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}",