Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-103092: Adapt _ctypes's PyCStgDict type to heap type #103932

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,9 @@ StructUnionType_new(PyTypeObject *type, PyObject *args, PyObject *kwds, int isSt
return NULL;
}

dict = (StgDictObject *)_PyObject_CallNoArgs((PyObject *)&PyCStgDict_Type);
ctypes_state *st = GLOBAL_STATE();
dict = (StgDictObject *)
_PyObject_CallNoArgs((PyObject *)st->PyCStgDict_Type);
if (!dict) {
Py_DECREF(result);
return NULL;
Expand Down Expand Up @@ -1087,8 +1089,9 @@ PyCPointerType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
stgdict items size, align, length contain info about pointers itself,
stgdict->proto has info about the pointed to type!
*/
ctypes_state *st = GLOBAL_STATE();
stgdict = (StgDictObject *)_PyObject_CallNoArgs(
(PyObject *)&PyCStgDict_Type);
(PyObject *)st->PyCStgDict_Type);
if (!stgdict)
return NULL;
stgdict->size = sizeof(void *);
Expand Down Expand Up @@ -1529,8 +1532,9 @@ PyCArrayType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
goto error;
}

ctypes_state *st = GLOBAL_STATE();
stgdict = (StgDictObject *)_PyObject_CallNoArgs(
(PyObject *)&PyCStgDict_Type);
(PyObject *)st->PyCStgDict_Type);
if (!stgdict)
goto error;

Expand Down Expand Up @@ -1975,8 +1979,9 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject
if (result == NULL)
return NULL;

ctypes_state *st = GLOBAL_STATE();
stgdict = (StgDictObject *)_PyObject_CallNoArgs(
(PyObject *)&PyCStgDict_Type);
(PyObject *)st->PyCStgDict_Type);
if (!stgdict) {
Py_DECREF(result);
return NULL;
Expand Down Expand Up @@ -2086,8 +2091,9 @@ PyCSimpleType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
goto error;
}

ctypes_state *st = GLOBAL_STATE();
stgdict = (StgDictObject *)_PyObject_CallNoArgs(
(PyObject *)&PyCStgDict_Type);
(PyObject *)st->PyCStgDict_Type);
if (!stgdict)
goto error;

Expand Down Expand Up @@ -2532,8 +2538,9 @@ PyCFuncPtrType_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
PyTypeObject *result;
StgDictObject *stgdict;

ctypes_state *st = GLOBAL_STATE();
stgdict = (StgDictObject *)_PyObject_CallNoArgs(
(PyObject *)&PyCStgDict_Type);
(PyObject *)st->PyCStgDict_Type);
if (!stgdict)
return NULL;

Expand Down Expand Up @@ -5684,7 +5691,7 @@ _ctypes_add_types(PyObject *mod)
CREATE_TYPE(mod, st->PyCThunk_Type, &cthunk_spec, NULL);
TYPE_READY(&PyCData_Type);
/* StgDict is derived from PyDict_Type */
TYPE_READY_BASE(&PyCStgDict_Type, &PyDict_Type);
CREATE_TYPE(mod, st->PyCStgDict_Type, &cstgdict_spec, &PyDict_Type);

/*************************************************
*
Expand Down
7 changes: 4 additions & 3 deletions Modules/_ctypes/ctypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ typedef struct {
PyTypeObject *DictRemover_Type;
PyTypeObject *PyCArg_Type;
PyTypeObject *PyCField_Type;
PyTypeObject *PyCStgDict_Type;
PyTypeObject *PyCThunk_Type;
#ifdef MS_WIN32
PyTypeObject *PyComError_Type;
Expand All @@ -49,6 +50,7 @@ extern ctypes_state global_state;

extern PyType_Spec carg_spec;
extern PyType_Spec cfield_spec;
extern PyType_Spec cstgdict_spec;
extern PyType_Spec cthunk_spec;

typedef struct tagPyCArgObject PyCArgObject;
Expand Down Expand Up @@ -140,9 +142,8 @@ typedef struct {
PyObject *paramflags;
} PyCFuncPtrObject;

extern PyTypeObject PyCStgDict_Type;
#define PyCStgDict_CheckExact(v) Py_IS_TYPE(v, &PyCStgDict_Type)
#define PyCStgDict_Check(v) PyObject_TypeCheck(v, &PyCStgDict_Type)
#define PyCStgDict_CheckExact(st, v) Py_IS_TYPE((v), (st)->PyCStgDict_Type)
#define PyCStgDict_Check(st, v) PyObject_TypeCheck((v), (st)->PyCStgDict_Type)

extern int PyCStructUnionType_update_stgdict(PyObject *fields, PyObject *type, int isStruct);
extern int PyType_stginfo(PyTypeObject *self, Py_ssize_t *psize, Py_ssize_t *palign, Py_ssize_t *plength);
Expand Down
78 changes: 35 additions & 43 deletions Modules/_ctypes/stgdict.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,18 @@ PyCStgDict_init(StgDictObject *self, PyObject *args, PyObject *kwds)
return 0;
}

static int
PyCStgDict_traverse(StgDictObject *self, visitproc visit, void *arg)
{
Py_VISIT(Py_TYPE(self));
Py_VISIT(self->proto);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe an extra visit to the proto member? The CDataType_traverse function in _ctypes.c has an explicit Py_VISIT(dict->proto).

Py_VISIT(self->argtypes);
Py_VISIT(self->converters);
Py_VISIT(self->restype);
Py_VISIT(self->checker);
return PyDict_Type.tp_traverse((PyObject *)self, visit, arg);
}

static int
PyCStgDict_clear(StgDictObject *self)
{
Expand All @@ -45,17 +57,20 @@ PyCStgDict_clear(StgDictObject *self)
Py_CLEAR(self->converters);
Py_CLEAR(self->restype);
Py_CLEAR(self->checker);
return 0;
return PyDict_Type.tp_clear((PyObject *)self);
}

static void
PyCStgDict_dealloc(StgDictObject *self)
{
PyTypeObject *tp = Py_TYPE(self);
PyObject_GC_UnTrack(self);
PyCStgDict_clear(self);
PyMem_Free(self->format);
PyMem_Free(self->shape);
PyMem_Free(self->ffi_type_pointer.elements);
PyDict_Type.tp_dealloc((PyObject *)self);
Py_DECREF(tp);
}

static PyObject *
Expand Down Expand Up @@ -136,46 +151,21 @@ static struct PyMethodDef PyCStgDict_methods[] = {
{NULL, NULL} /* sentinel */
};

PyTypeObject PyCStgDict_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
"StgDict",
sizeof(StgDictObject),
0,
(destructor)PyCStgDict_dealloc, /* tp_dealloc */
0, /* tp_vectorcall_offset */
0, /* tp_getattr */
0, /* tp_setattr */
0, /* tp_as_async */
0, /* tp_repr */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash */
0, /* tp_call */
0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
PyCStgDict_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
(initproc)PyCStgDict_init, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
0, /* tp_free */
static PyType_Slot cstgdict_slots[] = {
{Py_tp_dealloc, PyCStgDict_dealloc},
{Py_tp_traverse, PyCStgDict_traverse},
{Py_tp_clear, PyCStgDict_clear},
{Py_tp_methods, PyCStgDict_methods},
{Py_tp_init, PyCStgDict_init},
{0, NULL},
};

PyType_Spec cstgdict_spec = {
.name = "_ctypes.StgDict",
.basicsize = sizeof(StgDictObject),
.flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_IMMUTABLETYPE),
.slots = cstgdict_slots,
};

/* May return NULL, but does not set an exception! */
Expand All @@ -187,7 +177,8 @@ PyType_stgdict(PyObject *obj)
if (!PyType_Check(obj))
return NULL;
type = (PyTypeObject *)obj;
if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
ctypes_state *st = GLOBAL_STATE();
if (!type->tp_dict || !PyCStgDict_CheckExact(st, type->tp_dict))
return NULL;
return (StgDictObject *)type->tp_dict;
}
Expand All @@ -201,7 +192,8 @@ StgDictObject *
PyObject_stgdict(PyObject *self)
{
PyTypeObject *type = Py_TYPE(self);
if (!type->tp_dict || !PyCStgDict_CheckExact(type->tp_dict))
ctypes_state *st = GLOBAL_STATE();
if (!type->tp_dict || !PyCStgDict_CheckExact(st, type->tp_dict))
return NULL;
return (StgDictObject *)type->tp_dict;
}
Expand Down
2 changes: 0 additions & 2 deletions Tools/c-analyzer/cpython/globals-to-fix.tsv
Original file line number Diff line number Diff line change
Expand Up @@ -369,14 +369,12 @@ Modules/_ctypes/ctypes.h - PyCFuncPtr_Type -
Modules/_ctypes/ctypes.h - PyCPointerType_Type -
Modules/_ctypes/ctypes.h - PyCPointer_Type -
Modules/_ctypes/ctypes.h - PyCSimpleType_Type -
Modules/_ctypes/ctypes.h - PyCStgDict_Type -
Modules/_ctypes/ctypes.h - PyCStructType_Type -
Modules/_ctypes/ctypes.h - PyExc_ArgError -
Modules/_ctypes/ctypes.h - _ctypes_conversion_encoding -
Modules/_ctypes/ctypes.h - _ctypes_conversion_errors -
Modules/_ctypes/ctypes.h - _ctypes_ptrtype_cache -
Modules/_ctypes/ctypes.h - basespec_string -
Modules/_ctypes/stgdict.c - PyCStgDict_Type -
Modules/_cursesmodule.c - PyCursesWindow_Type -
Modules/_datetimemodule.c - PyDateTime_DateTimeType -
Modules/_datetimemodule.c - PyDateTime_DateType -
Expand Down
Loading