Skip to content

Commit be763e5

Browse files
gh-127945: fix thread safety and add lock held assertions to paramfunc in ctypes (#132473)
1 parent 522766a commit be763e5

File tree

3 files changed

+23
-40
lines changed

3 files changed

+23
-40
lines changed

Modules/_ctypes/_ctypes.c

+21-29
Original file line numberDiff line numberDiff line change
@@ -595,8 +595,14 @@ PyType_Spec pyctype_type_spec = {
595595
.slots = ctype_type_slots,
596596
};
597597

598+
/*
599+
PyCStructType_Type - a meta type/class. Creating a new class using this one as
600+
__metaclass__ will call the constructor StructUnionType_new.
601+
It initializes the C accessible fields somehow.
602+
*/
603+
598604
static PyCArgObject *
599-
StructUnionType_paramfunc_lock_held(ctypes_state *st, CDataObject *self)
605+
StructUnionType_paramfunc(ctypes_state *st, CDataObject *self)
600606
{
601607
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
602608
PyCArgObject *parg;
@@ -649,20 +655,6 @@ StructUnionType_paramfunc_lock_held(ctypes_state *st, CDataObject *self)
649655
return parg;
650656
}
651657

652-
/*
653-
PyCStructType_Type - a meta type/class. Creating a new class using this one as
654-
__metaclass__ will call the constructor StructUnionType_new.
655-
It initializes the C accessible fields somehow.
656-
*/
657-
static PyCArgObject *
658-
StructUnionType_paramfunc(ctypes_state *st, CDataObject *self)
659-
{
660-
PyCArgObject *res;
661-
Py_BEGIN_CRITICAL_SECTION(self);
662-
res = StructUnionType_paramfunc_lock_held(st, self);
663-
Py_END_CRITICAL_SECTION();
664-
return res;
665-
}
666658

667659
static int
668660
StructUnionType_init(PyObject *self, PyObject *args, PyObject *kwds, int isStruct)
@@ -1213,6 +1205,7 @@ PyCPointerType_SetProto(ctypes_state *st, StgInfo *stginfo, PyObject *proto)
12131205
static PyCArgObject *
12141206
PyCPointerType_paramfunc(ctypes_state *st, CDataObject *self)
12151207
{
1208+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
12161209
PyCArgObject *parg;
12171210

12181211
parg = PyCArgObject_new(st);
@@ -1222,7 +1215,7 @@ PyCPointerType_paramfunc(ctypes_state *st, CDataObject *self)
12221215
parg->tag = 'P';
12231216
parg->pffi_type = &ffi_type_pointer;
12241217
parg->obj = Py_NewRef(self);
1225-
parg->value.p = locked_deref(self);
1218+
parg->value.p = *(void **)self->b_ptr;
12261219
return parg;
12271220
}
12281221

@@ -1665,6 +1658,7 @@ add_getset(PyTypeObject *type, PyGetSetDef *gsp)
16651658
static PyCArgObject *
16661659
PyCArrayType_paramfunc(ctypes_state *st, CDataObject *self)
16671660
{
1661+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
16681662
PyCArgObject *p = PyCArgObject_new(st);
16691663
if (p == NULL)
16701664
return NULL;
@@ -2159,7 +2153,9 @@ c_void_p_from_param_impl(PyObject *type, PyTypeObject *cls, PyObject *value)
21592153
parg->tag = 'Z';
21602154
parg->obj = Py_NewRef(value);
21612155
/* Remember: b_ptr points to where the pointer is stored! */
2162-
parg->value.p = locked_deref((CDataObject *)value);
2156+
Py_BEGIN_CRITICAL_SECTION(value);
2157+
parg->value.p = *(void **)_CDataObject_CAST(value)->b_ptr;
2158+
Py_END_CRITICAL_SECTION();
21632159
return (PyObject *)parg;
21642160
}
21652161
}
@@ -2241,7 +2237,7 @@ static PyObject *CreateSwappedType(ctypes_state *st, PyTypeObject *type,
22412237
}
22422238

22432239
static PyCArgObject *
2244-
PyCSimpleType_paramfunc_lock_held(ctypes_state *st, CDataObject *self)
2240+
PyCSimpleType_paramfunc(ctypes_state *st, CDataObject *self)
22452241
{
22462242
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
22472243
const char *fmt;
@@ -2270,15 +2266,6 @@ PyCSimpleType_paramfunc_lock_held(ctypes_state *st, CDataObject *self)
22702266
return parg;
22712267
}
22722268

2273-
static PyCArgObject *
2274-
PyCSimpleType_paramfunc(ctypes_state *st, CDataObject *self)
2275-
{
2276-
PyCArgObject *res;
2277-
Py_BEGIN_CRITICAL_SECTION(self);
2278-
res = PyCSimpleType_paramfunc_lock_held(st, self);
2279-
Py_END_CRITICAL_SECTION();
2280-
return res;
2281-
}
22822269

22832270
static int
22842271
PyCSimpleType_init(PyObject *self, PyObject *args, PyObject *kwds)
@@ -2766,6 +2753,7 @@ make_funcptrtype_dict(ctypes_state *st, PyObject *attrdict, StgInfo *stginfo)
27662753
static PyCArgObject *
27672754
PyCFuncPtrType_paramfunc(ctypes_state *st, CDataObject *self)
27682755
{
2756+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED(self);
27692757
PyCArgObject *parg;
27702758

27712759
parg = PyCArgObject_new(st);
@@ -2775,7 +2763,7 @@ PyCFuncPtrType_paramfunc(ctypes_state *st, CDataObject *self)
27752763
parg->tag = 'P';
27762764
parg->pffi_type = &ffi_type_pointer;
27772765
parg->obj = Py_NewRef(self);
2778-
parg->value.p = locked_deref(self);
2766+
parg->value.p = *(void **)self->b_ptr;
27792767
return parg;
27802768
}
27812769

@@ -5827,7 +5815,11 @@ Pointer_subscript(PyObject *myself, PyObject *item)
58275815
static int
58285816
Pointer_bool(PyObject *self)
58295817
{
5830-
return locked_deref(_CDataObject_CAST(self)) != NULL;
5818+
int res;
5819+
Py_BEGIN_CRITICAL_SECTION(self);
5820+
res = *(void **)_CDataObject_CAST(self)->b_ptr != NULL;
5821+
Py_END_CRITICAL_SECTION();
5822+
return res;
58315823
}
58325824

58335825
static PyType_Slot pycpointer_slots[] = {

Modules/_ctypes/callproc.c

+2
Original file line numberDiff line numberDiff line change
@@ -683,7 +683,9 @@ static int ConvParam(ctypes_state *st,
683683
PyCArgObject *carg;
684684
assert(info->paramfunc);
685685
/* If it has an stginfo, it is a CDataObject */
686+
Py_BEGIN_CRITICAL_SECTION(obj);
686687
carg = info->paramfunc(st, (CDataObject *)obj);
688+
Py_END_CRITICAL_SECTION();
687689
if (carg == NULL)
688690
return -1;
689691
pa->ffi_type = carg->pffi_type;

Modules/_ctypes/ctypes.h

-11
Original file line numberDiff line numberDiff line change
@@ -643,14 +643,3 @@ PyStgInfo_Init(ctypes_state *state, PyTypeObject *type)
643643
info->initialized = 1;
644644
return info;
645645
}
646-
647-
/* Equivalent to *self->b_ptr with a lock. */
648-
static inline void *
649-
locked_deref(CDataObject *self)
650-
{
651-
void *ptr;
652-
Py_BEGIN_CRITICAL_SECTION(self);
653-
ptr = *(void **)self->b_ptr;
654-
Py_END_CRITICAL_SECTION();
655-
return ptr;
656-
}

0 commit comments

Comments
 (0)