Skip to content

Commit 82f74ec

Browse files
Test if PyCStgInfo_clone not share pointer_type cache
1 parent e1aaf45 commit 82f74ec

File tree

4 files changed

+42
-15
lines changed

4 files changed

+42
-15
lines changed

Lib/test/test_ctypes/test_structures.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,30 @@ class Test8(Union):
644644
self.assertEqual(ctx.exception.args[0], 'item 1 in _argtypes_ passes '
645645
'a union by value, which is unsupported.')
646646

647+
def test_do_not_share_pointer_type_cache_via_stginfo_clone(self):
648+
# This test case calls PyCStgInfo_clone()
649+
# for the Mid and Vector class definitions
650+
# and checks that pointer_type cache not shared
651+
# between subclasses.
652+
class Base(Structure):
653+
_fields_ = [('y', c_double),
654+
('x', c_double)]
655+
base_ptr = POINTER(Base)
656+
657+
class Mid(Base):
658+
pass
659+
Mid._fields_ = []
660+
mid_ptr = POINTER(Mid)
661+
662+
class Vector(Mid):
663+
pass
664+
665+
vector_ptr = POINTER(Vector)
666+
667+
self.assertIsNot(base_ptr, mid_ptr)
668+
self.assertIsNot(base_ptr, vector_ptr)
669+
self.assertIsNot(mid_ptr, vector_ptr)
670+
647671

648672
if __name__ == '__main__':
649673
unittest.main()

Modules/_ctypes/_ctypes.c

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,20 @@ ctype_clear_stginfo(StgInfo *info)
494494
Py_CLEAR(info->module); // decref the module last
495495
}
496496

497+
void
498+
ctype_free_stginfo_members(StgInfo *info)
499+
{
500+
assert(info);
501+
502+
PyMem_Free(info->ffi_type_pointer.elements);
503+
info->ffi_type_pointer.elements = NULL;
504+
PyMem_Free(info->format);
505+
info->format = NULL;
506+
PyMem_Free(info->shape);
507+
info->shape = NULL;
508+
ctype_clear_stginfo(info);
509+
}
510+
497511
static int
498512
CType_Type_clear(PyObject *self)
499513
{
@@ -517,13 +531,7 @@ CType_Type_dealloc(PyObject *self)
517531
"deallocating ctypes %R", self);
518532
}
519533
if (info) {
520-
PyMem_Free(info->ffi_type_pointer.elements);
521-
info->ffi_type_pointer.elements = NULL;
522-
PyMem_Free(info->format);
523-
info->format = NULL;
524-
PyMem_Free(info->shape);
525-
info->shape = NULL;
526-
ctype_clear_stginfo(info);
534+
ctype_free_stginfo_members(info);
527535
}
528536

529537
PyTypeObject *tp = Py_TYPE(self);

Modules/_ctypes/ctypes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ typedef struct {
378378

379379
extern int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info);
380380
extern void ctype_clear_stginfo(StgInfo *info);
381+
extern void ctype_free_stginfo_members(StgInfo *info);
381382

382383
typedef int(* PPROC)(void);
383384

Modules/_ctypes/stgdict.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,7 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info)
2525
{
2626
Py_ssize_t size;
2727

28-
ctype_clear_stginfo(dst_info);
29-
PyMem_Free(dst_info->ffi_type_pointer.elements);
30-
PyMem_Free(dst_info->format);
31-
dst_info->format = NULL;
32-
PyMem_Free(dst_info->shape);
33-
dst_info->shape = NULL;
34-
dst_info->ffi_type_pointer.elements = NULL;
28+
ctype_free_stginfo_members(dst_info);
3529

3630
memcpy(dst_info, src_info, sizeof(StgInfo));
3731

@@ -40,8 +34,8 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info)
4034
Py_XINCREF(dst_info->converters);
4135
Py_XINCREF(dst_info->restype);
4236
Py_XINCREF(dst_info->checker);
43-
dst_info->pointer_type = NULL; // the cache cannot be shared
4437
Py_XINCREF(dst_info->module);
38+
dst_info->pointer_type = NULL; // the cache cannot be shared
4539

4640
if (src_info->format) {
4741
dst_info->format = PyMem_Malloc(strlen(src_info->format) + 1);

0 commit comments

Comments
 (0)