]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-133290: Use PyObject_SetAttr to set _type_ (GH-133292) (GH-133295)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 2 May 2025 16:10:32 +0000 (18:10 +0200)
committerGitHub <noreply@github.com>
Fri, 2 May 2025 16:10:32 +0000 (18:10 +0200)
gh-133290: Use PyObject_SetAttr to set _type_ (GH-133292)
(cherry picked from commit 2590774c9bb96ec75ca8a13b0c061fcc9db3eb65)

Co-authored-by: Petr Viktorin <encukou@gmail.com>
Lib/test/test_ctypes/test_pointers.py
Misc/NEWS.d/next/Library/2025-05-02-13-16-44.gh-issue-133290.R5WrLM.rst [new file with mode: 0644]
Modules/_ctypes/_ctypes.c

index fc558e10ba40c57344b082b89e4a26115a0322f7..ed4541335dfca43e63c986a59710910bc2fc80b8 100644 (file)
@@ -224,6 +224,17 @@ class PointersTestCase(unittest.TestCase):
     def test_abstract(self):
         self.assertRaises(TypeError, _Pointer.set_type, 42)
 
+    def test_repeated_set_type(self):
+        # Regression test for gh-133290
+        class C(Structure):
+            _fields_ = [('a', c_int)]
+        ptr = POINTER(C)
+        # Read _type_ several times to warm up cache
+        for i in range(5):
+            self.assertIs(ptr._type_, C)
+        ptr.set_type(c_int)
+        self.assertIs(ptr._type_, c_int)
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2025-05-02-13-16-44.gh-issue-133290.R5WrLM.rst b/Misc/NEWS.d/next/Library/2025-05-02-13-16-44.gh-issue-133290.R5WrLM.rst
new file mode 100644 (file)
index 0000000..538cce9
--- /dev/null
@@ -0,0 +1,3 @@
+Fix attribute caching issue when setting :attr:`ctypes._Pointer._type_` in
+the undocumented and deprecated :func:`!ctypes.SetPointerType` function and the
+undocumented :meth:`!set_type` method.
index 3d7cb1b11648431c7fffe6012034122293cac9b6..7f843a201cdb1fd2f56868e1276fd8ef9e933121 100644 (file)
@@ -1280,34 +1280,24 @@ PyCPointerType_set_type_impl(PyTypeObject *self, PyTypeObject *cls,
                              PyObject *type)
 /*[clinic end generated code: output=51459d8f429a70ac input=67e1e8df921f123e]*/
 {
-    PyObject *attrdict = PyType_GetDict(self);
-    if (!attrdict) {
-        return NULL;
-    }
     ctypes_state *st = get_module_state_by_class(cls);
     StgInfo *info;
     if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) {
-        Py_DECREF(attrdict);
         return NULL;
     }
     if (!info) {
         PyErr_SetString(PyExc_TypeError,
                         "abstract class");
-        Py_DECREF(attrdict);
         return NULL;
     }
 
     if (PyCPointerType_SetProto(st, info, type) < 0) {
-        Py_DECREF(attrdict);
         return NULL;
     }
 
-    if (-1 == PyDict_SetItem(attrdict, &_Py_ID(_type_), type)) {
-        Py_DECREF(attrdict);
+    if (PyObject_SetAttr((PyObject *)self, &_Py_ID(_type_), type) < 0) {
         return NULL;
     }
-
-    Py_DECREF(attrdict);
     Py_RETURN_NONE;
 }