diff options
author | Ćukasz Langa <lukasz@langa.pl> | 2023-07-31 09:16:59 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-07-31 09:16:59 (GMT) |
commit | 57f27e444175a8a5ffcd86971e06de61c1c38628 (patch) | |
tree | d054c2fcabc91abbdea78d65e83dbab616be4134 /Modules | |
parent | aa5f2b1f3cdb5f71f5210d4578d5c68b6dd5e255 (diff) | |
download | cpython-57f27e444175a8a5ffcd86971e06de61c1c38628.zip cpython-57f27e444175a8a5ffcd86971e06de61c1c38628.tar.gz cpython-57f27e444175a8a5ffcd86971e06de61c1c38628.tar.bz2 |
[3.11] gh-46376: Return existing pointer when possible in ctypes (GH-107131) (#107488)
(cherry picked from commit 08447b5deb47e2a0df87fa0a0576d300e5c909b4)
Co-authored-by: Konstantin <kpp.live+github@gmail.com>
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_ctypes/_ctypes.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index fc73264..9cc5181 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5158,6 +5158,8 @@ static PyObject * Pointer_get_contents(CDataObject *self, void *closure) { StgDictObject *stgdict; + PyObject *keep, *ptr_probe; + CDataObject *ptr2ptr; if (*(void **)self->b_ptr == NULL) { PyErr_SetString(PyExc_ValueError, @@ -5167,6 +5169,33 @@ Pointer_get_contents(CDataObject *self, void *closure) stgdict = PyObject_stgdict((PyObject *)self); assert(stgdict); /* Cannot be NULL for pointer instances */ + + keep = GetKeepedObjects(self); + if (keep != NULL) { + // check if it's a pointer to a pointer: + // pointers will have '0' key in the _objects + ptr_probe = PyDict_GetItemString(keep, "0"); + + if (ptr_probe != NULL) { + ptr2ptr = (CDataObject*) PyDict_GetItemString(keep, "1"); + if (ptr2ptr == NULL) { + PyErr_SetString(PyExc_ValueError, + "Unexpected NULL pointer in _objects"); + return NULL; + } + // don't construct a new object, + // return existing one instead to preserve refcount + assert( + *(void**) self->b_ptr == ptr2ptr->b_ptr || + *(void**) self->b_value.c == ptr2ptr->b_ptr || + *(void**) self->b_ptr == ptr2ptr->b_value.c || + *(void**) self->b_value.c == ptr2ptr->b_value.c + ); // double-check that we are returning the same thing + Py_INCREF(ptr2ptr); + return (PyObject *) ptr2ptr; + } + } + return PyCData_FromBaseObj(stgdict->proto, (PyObject *)self, 0, *(void **)self->b_ptr); |