gh-133290: Use PyObject_SetAttr to set _type_ (GH-133292)

This commit is contained in:
Petr Viktorin 2025-05-02 14:47:07 +02:00 committed by GitHub
parent df8a02b1e1
commit 2590774c9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 15 additions and 11 deletions

View file

@ -224,6 +224,17 @@ def test_pointer_type_str_name(self):
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()

View file

@ -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.

View 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;
}