]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-133290: Use PyObject_SetAttr to set _type_ (GH-133292)
authorPetr Viktorin <encukou@gmail.com>
Fri, 2 May 2025 12:47:07 +0000 (14:47 +0200)
committerGitHub <noreply@github.com>
Fri, 2 May 2025 12:47:07 +0000 (14:47 +0200)
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 64030685ab0695790830f2bc7daa16f77346c64c..3605ca9007c9f82ce8f0ca97e5f525f835e70e7f 100644 (file)
@@ -1298,34 +1298,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;
 }