Skip to content

Commit 2590774

Browse files
authored
gh-133290: Use PyObject_SetAttr to set _type_ (GH-133292)
1 parent df8a02b commit 2590774

File tree

3 files changed

+15
-11
lines changed

3 files changed

+15
-11
lines changed

Lib/test/test_ctypes/test_pointers.py

+11
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,17 @@ def test_pointer_type_str_name(self):
224224
def test_abstract(self):
225225
self.assertRaises(TypeError, _Pointer.set_type, 42)
226226

227+
def test_repeated_set_type(self):
228+
# Regression test for gh-133290
229+
class C(Structure):
230+
_fields_ = [('a', c_int)]
231+
ptr = POINTER(C)
232+
# Read _type_ several times to warm up cache
233+
for i in range(5):
234+
self.assertIs(ptr._type_, C)
235+
ptr.set_type(c_int)
236+
self.assertIs(ptr._type_, c_int)
237+
227238

228239
if __name__ == '__main__':
229240
unittest.main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix attribute caching issue when setting :attr:`ctypes._Pointer._type_` in
2+
the undocumented and deprecated :func:`!ctypes.SetPointerType` function and the
3+
undocumented :meth:`!set_type` method.

Modules/_ctypes/_ctypes.c

+1-11
Original file line numberDiff line numberDiff line change
@@ -1298,34 +1298,24 @@ PyCPointerType_set_type_impl(PyTypeObject *self, PyTypeObject *cls,
12981298
PyObject *type)
12991299
/*[clinic end generated code: output=51459d8f429a70ac input=67e1e8df921f123e]*/
13001300
{
1301-
PyObject *attrdict = PyType_GetDict(self);
1302-
if (!attrdict) {
1303-
return NULL;
1304-
}
13051301
ctypes_state *st = get_module_state_by_class(cls);
13061302
StgInfo *info;
13071303
if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) {
1308-
Py_DECREF(attrdict);
13091304
return NULL;
13101305
}
13111306
if (!info) {
13121307
PyErr_SetString(PyExc_TypeError,
13131308
"abstract class");
1314-
Py_DECREF(attrdict);
13151309
return NULL;
13161310
}
13171311

13181312
if (PyCPointerType_SetProto(st, info, type) < 0) {
1319-
Py_DECREF(attrdict);
13201313
return NULL;
13211314
}
13221315

1323-
if (-1 == PyDict_SetItem(attrdict, &_Py_ID(_type_), type)) {
1324-
Py_DECREF(attrdict);
1316+
if (PyObject_SetAttr((PyObject *)self, &_Py_ID(_type_), type) < 0) {
13251317
return NULL;
13261318
}
1327-
1328-
Py_DECREF(attrdict);
13291319
Py_RETURN_NONE;
13301320
}
13311321

0 commit comments

Comments
 (0)