From 72514aacdfdac0533744917c68905ced14dac6a5 Mon Sep 17 00:00:00 2001 From: neonene Date: Fri, 22 Mar 2024 08:37:36 +0900 Subject: [PATCH 1/9] multi-phase with global state --- Modules/_ctypes/_ctypes.c | 248 ++++++++++++-------- Modules/_ctypes/callproc.c | 31 +-- Modules/_ctypes/ctypes.h | 15 +- Tools/c-analyzer/cpython/globals-to-fix.tsv | 4 +- 4 files changed, 172 insertions(+), 126 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index af094a0fb59e27..99e6047e437b97 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -128,16 +128,6 @@ bytes(cdata) ctypes_state global_state = {0}; -PyObject *PyExc_ArgError = NULL; - -/* This dict maps ctypes types to POINTER types */ -PyObject *_ctypes_ptrtype_cache = NULL; - -/* a callable object used for unpickling: - strong reference to _ctypes._unpickle() function */ -static PyObject *_unpickle; - - /****************************************************************/ typedef struct { @@ -452,7 +442,22 @@ static int CType_Type_traverse(PyObject *self, visitproc visit, void *arg) { Py_VISIT(Py_TYPE(self)); - return 0; + + ctypes_state *st = GLOBAL_STATE(); + if (st && st->PyCType_Type) { + StgInfo *info; + if (PyStgInfo_FromType(st, self, &info) < 0) { + return -1; + } + if (info) { + Py_VISIT(info->proto); + Py_VISIT(info->argtypes); + Py_VISIT(info->converters); + Py_VISIT(info->restype); + Py_VISIT(info->checker); + } + } + return PyType_Type.tp_traverse(self, visit, arg); } static void @@ -479,7 +484,7 @@ CType_Type_clear(PyObject *self) _ctype_clear_stginfo(info); } } - return 0; + return PyType_Type.tp_clear(self); } static void @@ -993,35 +998,6 @@ CDataType_repeat(PyObject *self, Py_ssize_t length) return PyCArrayType_from_ctype(self, length); } -static int -CDataType_clear(PyTypeObject *self) -{ - ctypes_state *st = GLOBAL_STATE(); - StgInfo *info; - if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - return -1; - } - if (info) { - Py_CLEAR(info->proto); - } - return PyType_Type.tp_clear((PyObject *)self); -} - -static int -CDataType_traverse(PyTypeObject *self, visitproc visit, void *arg) -{ - ctypes_state *st = GLOBAL_STATE(); - StgInfo *info; - if (PyStgInfo_FromType(st, (PyObject *)self, &info) < 0) { - return -1; - } - if (info) { - Py_VISIT(info->proto); - } - Py_VISIT(Py_TYPE(self)); - return PyType_Type.tp_traverse((PyObject *)self, visit, arg); -} - static int PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value) { @@ -1052,8 +1028,6 @@ UnionType_setattro(PyObject *self, PyObject *key, PyObject *value) static PyType_Slot pycstruct_type_slots[] = { {Py_tp_setattro, PyCStructType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the CData Objects")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCStructType_init}, @@ -1064,7 +1038,7 @@ static PyType_Slot pycstruct_type_slots[] = { static PyType_Spec pycstruct_type_spec = { .name = "_ctypes.PyCStructType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycstruct_type_slots, }; @@ -1072,8 +1046,6 @@ static PyType_Spec pycstruct_type_spec = { static PyType_Slot union_type_slots[] = { {Py_tp_setattro, UnionType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the Union Objects")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, UnionType_init}, @@ -1084,7 +1056,7 @@ static PyType_Slot union_type_slots[] = { static PyType_Spec union_type_spec = { .name = "_ctypes.UnionType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = union_type_slots, }; @@ -1311,8 +1283,6 @@ static PyMethodDef PyCPointerType_methods[] = { static PyType_Slot pycpointer_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Pointer Objects")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, PyCPointerType_methods}, {Py_tp_init, PyCPointerType_init}, @@ -1323,7 +1293,7 @@ static PyType_Slot pycpointer_type_slots[] = { static PyType_Spec pycpointer_type_spec = { .name = "_ctypes.PyCPointerType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycpointer_type_slots, }; @@ -1646,10 +1616,8 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycarray_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Array Objects")}, - {Py_tp_traverse, CDataType_traverse}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCArrayType_init}, - {Py_tp_clear, CDataType_clear}, // Sequence protocol. {Py_sq_repeat, CDataType_repeat}, @@ -1658,7 +1626,7 @@ static PyType_Slot pycarray_type_slots[] = { static PyType_Spec pycarray_type_spec = { .name = "_ctypes.PyCArrayType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycarray_type_slots, }; @@ -1976,25 +1944,26 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject PyObject *name = PyTuple_GET_ITEM(args, 0); PyObject *newname; PyObject *swapped_args; - static PyObject *suffix; Py_ssize_t i; swapped_args = PyTuple_New(PyTuple_GET_SIZE(args)); if (!swapped_args) return NULL; - if (suffix == NULL) + ctypes_state *st = GLOBAL_STATE(); + if (st->swapped_suffix == NULL) { #ifdef WORDS_BIGENDIAN - suffix = PyUnicode_InternFromString("_le"); + st->swapped_suffix = PyUnicode_InternFromString("_le"); #else - suffix = PyUnicode_InternFromString("_be"); + st->swapped_suffix = PyUnicode_InternFromString("_be"); #endif - if (suffix == NULL) { + } + if (st->swapped_suffix == NULL) { Py_DECREF(swapped_args); return NULL; } - newname = PyUnicode_Concat(name, suffix); + newname = PyUnicode_Concat(name, st->swapped_suffix); if (newname == NULL) { Py_DECREF(swapped_args); return NULL; @@ -2014,8 +1983,6 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject if (result == NULL) return NULL; - ctypes_state *st = GLOBAL_STATE(); - StgInfo *stginfo = PyStgInfo_Init(st, result); if (!stginfo) { Py_DECREF(result); @@ -2322,8 +2289,6 @@ static PyType_Slot pycsimple_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the PyCSimpleType Objects")}, {Py_tp_methods, PyCSimpleType_methods}, {Py_tp_init, PyCSimpleType_init}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, // Sequence protocol. {Py_sq_repeat, CDataType_repeat}, @@ -2332,7 +2297,7 @@ static PyType_Slot pycsimple_type_slots[] = { static PyType_Spec pycsimple_type_spec = { .name = "_ctypes.PyCSimpleType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycsimple_type_slots, }; @@ -2358,7 +2323,8 @@ converters_from_argtypes(PyObject *ob) Py_ssize_t nArgs = PyTuple_GET_SIZE(ob); if (nArgs > CTYPES_MAX_ARGCOUNT) { Py_DECREF(ob); - PyErr_Format(PyExc_ArgError, + ctypes_state *st = GLOBAL_STATE(); + PyErr_Format(st->PyExc_ArgError, "_argtypes_ has too many arguments (%zi), maximum is %i", nArgs, CTYPES_MAX_ARGCOUNT); return NULL; @@ -2578,8 +2544,6 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycfuncptr_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for C function pointers")}, - {Py_tp_traverse, CDataType_traverse}, - {Py_tp_clear, CDataType_clear}, {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCFuncPtrType_init}, @@ -2590,7 +2554,7 @@ static PyType_Slot pycfuncptr_type_slots[] = { static PyType_Spec pycfuncptr_type_spec = { .name = "_ctypes.PyCFuncPtrType", - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC | + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_IMMUTABLETYPE), .slots = pycfuncptr_type_slots, }; @@ -2843,7 +2807,7 @@ PyCData_reduce(PyObject *myself, PyObject *args) if (dict == NULL) { return NULL; } - return Py_BuildValue("O(O(NN))", _unpickle, Py_TYPE(myself), dict, + return Py_BuildValue("O(O(NN))", st->_unpickle, Py_TYPE(myself), dict, PyBytes_FromStringAndSize(self->b_ptr, self->b_size)); } @@ -4791,14 +4755,14 @@ static PyType_Spec pycarray_spec = { PyObject * PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) { - static PyObject *cache; PyObject *key; char name[256]; PyObject *len; - if (cache == NULL) { - cache = PyDict_New(); - if (cache == NULL) + ctypes_state *st = GLOBAL_STATE(); + if (st->array_cache == NULL) { + st->array_cache = PyDict_New(); + if (st->array_cache == NULL) return NULL; } len = PyLong_FromSsize_t(length); @@ -4810,7 +4774,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) return NULL; PyObject *result; - if (_PyDict_GetItemProxy(cache, key, &result) != 0) { + if (_PyDict_GetItemProxy(st->array_cache, key, &result) != 0) { // found or error Py_DECREF(key); return result; @@ -4829,7 +4793,6 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) sprintf(name, "%.200s_Array_%ld", ((PyTypeObject *)itemtype)->tp_name, (long)length); #endif - ctypes_state *st = GLOBAL_STATE(); result = PyObject_CallFunction((PyObject *)st->PyCArrayType_Type, "s(O){s:n,s:O}", name, @@ -4843,7 +4806,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) Py_DECREF(key); return NULL; } - if (-1 == PyDict_SetItemProxy(cache, key, result)) { + if (PyDict_SetItemProxy(st->array_cache, key, result) < 0) { Py_DECREF(key); Py_DECREF(result); return NULL; @@ -5535,15 +5498,6 @@ wstring_at(const wchar_t *ptr, int size) } -static struct PyModuleDef _ctypesmodule = { - PyModuleDef_HEAD_INIT, - .m_name = "_ctypes", - .m_doc = _ctypes__doc__, - .m_size = -1, - .m_methods = _ctypes_module_methods, -}; - - static int _ctypes_add_types(PyObject *mod) { @@ -5652,10 +5606,10 @@ _ctypes_add_objects(PyObject *mod) } \ } while (0) - MOD_ADD("_pointer_type_cache", Py_NewRef(_ctypes_ptrtype_cache)); + ctypes_state *st = GLOBAL_STATE(); + MOD_ADD("_pointer_type_cache", Py_NewRef(st->_ctypes_ptrtype_cache)); #ifdef MS_WIN32 - ctypes_state *st = GLOBAL_STATE(); MOD_ADD("COMError", Py_NewRef(st->PyComError_Type)); MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT)); MOD_ADD("FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL)); @@ -5685,7 +5639,7 @@ _ctypes_add_objects(PyObject *mod) MOD_ADD("RTLD_LOCAL", PyLong_FromLong(RTLD_LOCAL)); MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL)); MOD_ADD("CTYPES_MAX_ARGCOUNT", PyLong_FromLong(CTYPES_MAX_ARGCOUNT)); - MOD_ADD("ArgumentError", Py_NewRef(PyExc_ArgError)); + MOD_ADD("ArgumentError", Py_NewRef(st->PyExc_ArgError)); MOD_ADD("SIZEOF_TIME_T", PyLong_FromSsize_t(SIZEOF_TIME_T)); return 0; #undef MOD_ADD @@ -5695,18 +5649,19 @@ _ctypes_add_objects(PyObject *mod) static int _ctypes_mod_exec(PyObject *mod) { - _unpickle = PyObject_GetAttrString(mod, "_unpickle"); - if (_unpickle == NULL) { + ctypes_state *st = GLOBAL_STATE(); + st->_unpickle = PyObject_GetAttrString(mod, "_unpickle"); + if (st->_unpickle == NULL) { return -1; } - _ctypes_ptrtype_cache = PyDict_New(); - if (_ctypes_ptrtype_cache == NULL) { + st->_ctypes_ptrtype_cache = PyDict_New(); + if (st->_ctypes_ptrtype_cache == NULL) { return -1; } - PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); - if (!PyExc_ArgError) { + st->PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); + if (!st->PyExc_ArgError) { return -1; } @@ -5721,19 +5676,104 @@ _ctypes_mod_exec(PyObject *mod) } +static int +module_traverse(PyObject *module, visitproc visit, void *arg) { + ctypes_state *st = GLOBAL_STATE(); + Py_VISIT(st->_ctypes_ptrtype_cache); + Py_VISIT(st->_unpickle); + Py_VISIT(st->array_cache); + Py_VISIT(st->error_object_name); + Py_VISIT(st->PyExc_ArgError); + Py_VISIT(st->swapped_suffix); + + Py_VISIT(st->DictRemover_Type); + Py_VISIT(st->PyCArg_Type); + Py_VISIT(st->PyCField_Type); + Py_VISIT(st->PyCThunk_Type); + Py_VISIT(st->StructParam_Type); + Py_VISIT(st->PyCStructType_Type); + Py_VISIT(st->UnionType_Type); + Py_VISIT(st->PyCPointerType_Type); + Py_VISIT(st->PyCArrayType_Type); + Py_VISIT(st->PyCSimpleType_Type); + Py_VISIT(st->PyCFuncPtrType_Type); + Py_VISIT(st->PyCData_Type); + Py_VISIT(st->Struct_Type); + Py_VISIT(st->Union_Type); + Py_VISIT(st->PyCArray_Type); + Py_VISIT(st->Simple_Type); + Py_VISIT(st->PyCPointer_Type); + Py_VISIT(st->PyCFuncPtr_Type); +#ifdef MS_WIN32 + Py_VISIT(st->PyComError_Type); +#endif + Py_VISIT(st->PyCType_Type); + return 0; +} + +static int +module_clear(PyObject *module) { + ctypes_state *st = GLOBAL_STATE(); + Py_CLEAR(st->_ctypes_ptrtype_cache); + Py_CLEAR(st->_unpickle); + Py_CLEAR(st->array_cache); + Py_CLEAR(st->error_object_name); + Py_CLEAR(st->PyExc_ArgError); + Py_CLEAR(st->swapped_suffix); + + Py_CLEAR(st->DictRemover_Type); + Py_CLEAR(st->PyCArg_Type); + Py_CLEAR(st->PyCField_Type); + Py_CLEAR(st->PyCThunk_Type); + Py_CLEAR(st->StructParam_Type); + Py_CLEAR(st->PyCStructType_Type); + Py_CLEAR(st->UnionType_Type); + Py_CLEAR(st->PyCPointerType_Type); + Py_CLEAR(st->PyCArrayType_Type); + Py_CLEAR(st->PyCSimpleType_Type); + Py_CLEAR(st->PyCFuncPtrType_Type); + Py_CLEAR(st->PyCData_Type); + Py_CLEAR(st->Struct_Type); + Py_CLEAR(st->Union_Type); + Py_CLEAR(st->PyCArray_Type); + Py_CLEAR(st->Simple_Type); + Py_CLEAR(st->PyCPointer_Type); + Py_CLEAR(st->PyCFuncPtr_Type); +#ifdef MS_WIN32 + Py_CLEAR(st->PyComError_Type); +#endif + Py_CLEAR(st->PyCType_Type); + return 0; +} + +static void +module_free(void *module) +{ + (void)module_clear((PyObject *)module); +} + +static PyModuleDef_Slot module_slots[] = { + {Py_mod_exec, _ctypes_mod_exec}, + // {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, + {0, NULL} +}; + +struct PyModuleDef _ctypesmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_ctypes", + .m_doc = _ctypes__doc__, + .m_size = 0, + .m_methods = _ctypes_module_methods, + .m_slots = module_slots, + .m_traverse = module_traverse, + .m_clear = module_clear, + .m_free = module_free, +}; + PyMODINIT_FUNC PyInit__ctypes(void) { - PyObject *mod = PyModule_Create(&_ctypesmodule); - if (!mod) { - return NULL; - } - - if (_ctypes_mod_exec(mod) < 0) { - Py_DECREF(mod); - return NULL; - } - return mod; + return PyModuleDef_Init(&_ctypesmodule); } /* diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 6ebbb64d61b07a..591bbce5185209 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -157,18 +157,18 @@ _ctypes_get_errobj(int **pspace) { PyObject *dict = PyThreadState_GetDict(); PyObject *errobj; - static PyObject *error_object_name; if (dict == NULL) { PyErr_SetString(PyExc_RuntimeError, "cannot get thread state"); return NULL; } - if (error_object_name == NULL) { - error_object_name = PyUnicode_InternFromString("ctypes.error_object"); - if (error_object_name == NULL) + ctypes_state *st = GLOBAL_STATE(); + if (st->error_object_name == NULL) { + st->error_object_name = PyUnicode_InternFromString("ctypes.error_object"); + if (st->error_object_name == NULL) return NULL; } - if (PyDict_GetItemRef(dict, error_object_name, &errobj) < 0) { + if (PyDict_GetItemRef(dict, st->error_object_name, &errobj) < 0) { return NULL; } if (errobj) { @@ -188,8 +188,7 @@ _ctypes_get_errobj(int **pspace) PyMem_Free(space); return NULL; } - if (-1 == PyDict_SetItem(dict, error_object_name, - errobj)) { + if (PyDict_SetItem(dict, st->error_object_name, errobj) < 0) { Py_DECREF(errobj); return NULL; } @@ -1197,9 +1196,10 @@ PyObject *_ctypes_callproc(PPROC pProc, ++argcount; #endif + ctypes_state *st = GLOBAL_STATE(); if (argcount > CTYPES_MAX_ARGCOUNT) { - PyErr_Format(PyExc_ArgError, "too many arguments (%zi), maximum is %i", + PyErr_Format(st->PyExc_ArgError, "too many arguments (%zi), maximum is %i", argcount, CTYPES_MAX_ARGCOUNT); return NULL; } @@ -1232,20 +1232,20 @@ PyObject *_ctypes_callproc(PPROC pProc, converter = PyTuple_GET_ITEM(argtypes, i); v = PyObject_CallOneArg(converter, arg); if (v == NULL) { - _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; } err = ConvParam(v, i+1, pa); Py_DECREF(v); if (-1 == err) { - _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; } } else { err = ConvParam(arg, i+1, pa); if (-1 == err) { - _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; /* leaking ? */ } } @@ -1949,11 +1949,11 @@ create_pointer_type(PyObject *module, PyObject *cls) PyTypeObject *typ; PyObject *key; - if (PyDict_GetItemRef(_ctypes_ptrtype_cache, cls, &result) != 0) { + ctypes_state *st = GLOBAL_STATE(); + if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, cls, &result) != 0) { // found or error return result; } - ctypes_state *st = GLOBAL_STATE(); // not found if (PyUnicode_CheckExact(cls)) { PyObject *name = PyUnicode_FromFormat("LP_%U", cls); @@ -1983,7 +1983,7 @@ create_pointer_type(PyObject *module, PyObject *cls) PyErr_SetString(PyExc_TypeError, "must be a ctypes type"); return NULL; } - if (-1 == PyDict_SetItem(_ctypes_ptrtype_cache, key, result)) { + if (PyDict_SetItem(st->_ctypes_ptrtype_cache, key, result) < 0) { Py_DECREF(result); Py_DECREF(key); return NULL; @@ -2012,7 +2012,8 @@ create_pointer_inst(PyObject *module, PyObject *arg) PyObject *result; PyObject *typ; - if (PyDict_GetItemRef(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { + ctypes_state *st = GLOBAL_STATE(); + if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { return NULL; } if (typ == NULL) { diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index d7d725a4fdf669..a10daf06540376 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -42,6 +42,7 @@ typedef struct { PyTypeObject *PyCField_Type; PyTypeObject *PyCThunk_Type; PyTypeObject *StructParam_Type; + PyTypeObject *PyCType_Type; PyTypeObject *PyCStructType_Type; PyTypeObject *UnionType_Type; PyTypeObject *PyCPointerType_Type; @@ -58,7 +59,15 @@ typedef struct { #ifdef MS_WIN32 PyTypeObject *PyComError_Type; #endif - PyTypeObject *PyCType_Type; + /* This dict maps ctypes types to POINTER types */ + PyObject *_ctypes_ptrtype_cache; + /* a callable object used for unpickling: + strong reference to _ctypes._unpickle() function */ + PyObject *_unpickle; + PyObject *array_cache; + PyObject *error_object_name; // callproc.c + PyObject *PyExc_ArgError; + PyObject *swapped_suffix; } ctypes_state; extern ctypes_state global_state; @@ -375,9 +384,6 @@ extern char basespec_string[]; extern ffi_type *_ctypes_get_ffi_type(PyObject *obj); -/* exception classes */ -extern PyObject *PyExc_ArgError; - extern char *_ctypes_conversion_encoding; extern char *_ctypes_conversion_errors; @@ -393,7 +399,6 @@ extern char *_ctypes_alloc_format_string_with_shape(int ndim, extern int _ctypes_simple_instance(PyObject *obj); -extern PyObject *_ctypes_ptrtype_cache; PyObject *_ctypes_get_errobj(int **pspace); #ifdef USING_MALLOC_CLOSURE_DOT_C diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 92fab9b3998636..65f94e50e1bd7d 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -416,14 +416,14 @@ Modules/xxmodule.c - ErrorObject - ## manually cached PyUnicodeOjbect Modules/_ctypes/callproc.c _ctypes_get_errobj error_object_name - -Modules/_ctypes/_ctypes.c CreateSwappedType suffix - +Modules/_ctypes/_ctypes.c CreateSwappedType swapped_suffix - ##----------------------- ## other ## initialized once Modules/_ctypes/_ctypes.c - _unpickle - -Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype cache - +Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype array_cache - Modules/_cursesmodule.c - ModDict - Modules/_datetimemodule.c datetime_strptime module - From 2a2ee7ba9156156a5e804ce3b6515f2eebdb197f Mon Sep 17 00:00:00 2001 From: neonene Date: Fri, 22 Mar 2024 10:00:26 +0900 Subject: [PATCH 2/9] inherit Py_sq_repeat / CDataType -> CType_Type --- Modules/_ctypes/_ctypes.c | 114 +++++++++++++++++--------------------- 1 file changed, 50 insertions(+), 64 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 99e6047e437b97..4e23b60eb17335 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -543,23 +543,6 @@ static PyMethodDef ctype_methods[] = { {0}, }; -static PyType_Slot ctype_type_slots[] = { - {Py_tp_traverse, CType_Type_traverse}, - {Py_tp_clear, CType_Type_clear}, - {Py_tp_dealloc, CType_Type_dealloc}, - {Py_tp_methods, ctype_methods}, - {0, NULL}, -}; - -static PyType_Spec pyctype_type_spec = { - .name = "_ctypes.CType_Type", - .basicsize = -(Py_ssize_t)sizeof(StgInfo), - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | - Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE ), - .slots = ctype_type_slots, -}; - /* PyCStructType_Type - a meta type/class. Creating a new class using this one as __metaclass__ will call the constructor StructUnionType_new. @@ -709,7 +692,7 @@ PyDoc_STRVAR(from_address_doc, "C.from_address(integer) -> C instance\naccess a C instance at the specified address"); static PyObject * -CDataType_from_address(PyObject *type, PyObject *value) +CTypeType_from_address(PyObject *type, PyObject *value) { void *buf; if (!PyLong_Check(value)) { @@ -730,7 +713,7 @@ static int KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep); static PyObject * -CDataType_from_buffer(PyObject *type, PyObject *args) +CTypeType_from_buffer(PyObject *type, PyObject *args) { PyObject *obj; PyObject *mv; @@ -814,7 +797,7 @@ static PyObject * GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * -CDataType_from_buffer_copy(PyObject *type, PyObject *args) +CTypeType_from_buffer_copy(PyObject *type, PyObject *args) { Py_buffer buffer; Py_ssize_t offset = 0; @@ -867,7 +850,7 @@ PyDoc_STRVAR(in_dll_doc, "C.in_dll(dll, name) -> C instance\naccess a C instance in a dll"); static PyObject * -CDataType_in_dll(PyObject *type, PyObject *args) +CTypeType_in_dll(PyObject *type, PyObject *args) { PyObject *dll; char *name; @@ -929,7 +912,7 @@ PyDoc_STRVAR(from_param_doc, "Convert a Python object into a function call parameter."); static PyObject * -CDataType_from_param(PyObject *type, PyObject *value) +CTypeType_from_param(PyObject *type, PyObject *value) { PyObject *as_parameter; int res = PyObject_IsInstance(value, type); @@ -968,7 +951,7 @@ CDataType_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { - value = CDataType_from_param(type, as_parameter); + value = CTypeType_from_param(type, as_parameter); Py_DECREF(as_parameter); return value; } @@ -979,17 +962,8 @@ CDataType_from_param(PyObject *type, PyObject *value) return NULL; } -static PyMethodDef CDataType_methods[] = { - { "from_param", CDataType_from_param, METH_O, from_param_doc }, - { "from_address", CDataType_from_address, METH_O, from_address_doc }, - { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc }, - { NULL, NULL }, -}; - static PyObject * -CDataType_repeat(PyObject *self, Py_ssize_t length) +CTypeType_repeat(PyObject *self, Py_ssize_t length) { if (length < 0) return PyErr_Format(PyExc_ValueError, @@ -998,6 +972,36 @@ CDataType_repeat(PyObject *self, Py_ssize_t length) return PyCArrayType_from_ctype(self, length); } +static PyType_Slot ctype_type_slots[] = { + {Py_tp_traverse, CType_Type_traverse}, + {Py_tp_clear, CType_Type_clear}, + {Py_tp_dealloc, CType_Type_dealloc}, + {Py_tp_methods, ctype_methods}, + + // Sequence protocol. + {Py_sq_repeat, CTypeType_repeat}, + {0, NULL}, +}; + +static PyType_Spec pyctype_type_spec = { + .name = "_ctypes.CType_Type", + .basicsize = -(Py_ssize_t)sizeof(StgInfo), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE ), + .slots = ctype_type_slots, +}; + +static PyMethodDef CTypeType_methods[] = { + { "from_param", CTypeType_from_param, METH_O, from_param_doc }, + { "from_address", CTypeType_from_address, METH_O, from_address_doc }, + { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, + { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc }, + { NULL, NULL }, +}; + + static int PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value) { @@ -1028,11 +1032,8 @@ UnionType_setattro(PyObject *self, PyObject *key, PyObject *value) static PyType_Slot pycstruct_type_slots[] = { {Py_tp_setattro, PyCStructType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the CData Objects")}, - {Py_tp_methods, CDataType_methods}, + {Py_tp_methods, CTypeType_methods}, {Py_tp_init, PyCStructType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; @@ -1046,11 +1047,8 @@ static PyType_Spec pycstruct_type_spec = { static PyType_Slot union_type_slots[] = { {Py_tp_setattro, UnionType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the Union Objects")}, - {Py_tp_methods, CDataType_methods}, + {Py_tp_methods, CTypeType_methods}, {Py_tp_init, UnionType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; @@ -1268,14 +1266,14 @@ PyCPointerType_from_param(PyObject *type, PyObject *value) return Py_NewRef(value); } } - return CDataType_from_param(type, value); + return CTypeType_from_param(type, value); } static PyMethodDef PyCPointerType_methods[] = { - { "from_address", CDataType_from_address, METH_O, from_address_doc }, - { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, + { "from_address", CTypeType_from_address, METH_O, from_address_doc }, + { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, + { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc}, { "from_param", (PyCFunction)PyCPointerType_from_param, METH_O, from_param_doc}, { "set_type", (PyCFunction)PyCPointerType_set_type, METH_O }, { NULL, NULL }, @@ -1285,9 +1283,6 @@ static PyType_Slot pycpointer_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Pointer Objects")}, {Py_tp_methods, PyCPointerType_methods}, {Py_tp_init, PyCPointerType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; @@ -1616,11 +1611,8 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycarray_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Array Objects")}, - {Py_tp_methods, CDataType_methods}, + {Py_tp_methods, CTypeType_methods}, {Py_tp_init, PyCArrayType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; @@ -2278,10 +2270,10 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) static PyMethodDef PyCSimpleType_methods[] = { { "from_param", PyCSimpleType_from_param, METH_O, from_param_doc }, - { "from_address", CDataType_from_address, METH_O, from_address_doc }, - { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, + { "from_address", CTypeType_from_address, METH_O, from_address_doc }, + { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, + { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc}, { NULL, NULL }, }; @@ -2289,9 +2281,6 @@ static PyType_Slot pycsimple_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the PyCSimpleType Objects")}, {Py_tp_methods, PyCSimpleType_methods}, {Py_tp_init, PyCSimpleType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; @@ -2544,11 +2533,8 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycfuncptr_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for C function pointers")}, - {Py_tp_methods, CDataType_methods}, + {Py_tp_methods, CTypeType_methods}, {Py_tp_init, PyCFuncPtrType_init}, - - // Sequence protocol. - {Py_sq_repeat, CDataType_repeat}, {0, NULL}, }; From 26bc72a0631efcf6a03e346339e92921749b98e5 Mon Sep 17 00:00:00 2001 From: neonene Date: Fri, 22 Mar 2024 10:45:05 +0900 Subject: [PATCH 3/9] mix CDataType_methods into ctype_methods / nit --- Modules/_ctypes/_ctypes.c | 34 +++++++++++++++------------------- Modules/_ctypes/callproc.c | 2 +- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 4e23b60eb17335..fc2f5e7803b44e 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -537,12 +537,6 @@ CType_Type_sizeof(PyObject *self) return PyLong_FromSsize_t(size); } -static PyMethodDef ctype_methods[] = { - {"__sizeof__", _PyCFunction_CAST(CType_Type_sizeof), - METH_NOARGS, PyDoc_STR("Return memory consumption of the type object.")}, - {0}, -}; - /* PyCStructType_Type - a meta type/class. Creating a new class using this one as __metaclass__ will call the constructor StructUnionType_new. @@ -972,6 +966,17 @@ CTypeType_repeat(PyObject *self, Py_ssize_t length) return PyCArrayType_from_ctype(self, length); } +static PyMethodDef ctype_methods[] = { + {"__sizeof__", _PyCFunction_CAST(CType_Type_sizeof), + METH_NOARGS, PyDoc_STR("Return memory consumption of the type object.")}, + { "from_param", CTypeType_from_param, METH_O, from_param_doc }, + { "from_address", CTypeType_from_address, METH_O, from_address_doc }, + { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, + { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc }, + { NULL, NULL }, +}; + static PyType_Slot ctype_type_slots[] = { {Py_tp_traverse, CType_Type_traverse}, {Py_tp_clear, CType_Type_clear}, @@ -992,15 +997,6 @@ static PyType_Spec pyctype_type_spec = { .slots = ctype_type_slots, }; -static PyMethodDef CTypeType_methods[] = { - { "from_param", CTypeType_from_param, METH_O, from_param_doc }, - { "from_address", CTypeType_from_address, METH_O, from_address_doc }, - { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc }, - { NULL, NULL }, -}; - static int PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value) @@ -1032,7 +1028,7 @@ UnionType_setattro(PyObject *self, PyObject *key, PyObject *value) static PyType_Slot pycstruct_type_slots[] = { {Py_tp_setattro, PyCStructType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the CData Objects")}, - {Py_tp_methods, CTypeType_methods}, + {Py_tp_methods, ctype_methods}, {Py_tp_init, PyCStructType_init}, {0, NULL}, }; @@ -1047,7 +1043,7 @@ static PyType_Spec pycstruct_type_spec = { static PyType_Slot union_type_slots[] = { {Py_tp_setattro, UnionType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the Union Objects")}, - {Py_tp_methods, CTypeType_methods}, + {Py_tp_methods, ctype_methods}, {Py_tp_init, UnionType_init}, {0, NULL}, }; @@ -1611,7 +1607,7 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycarray_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Array Objects")}, - {Py_tp_methods, CTypeType_methods}, + {Py_tp_methods, ctype_methods}, {Py_tp_init, PyCArrayType_init}, {0, NULL}, }; @@ -2533,7 +2529,7 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycfuncptr_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for C function pointers")}, - {Py_tp_methods, CTypeType_methods}, + {Py_tp_methods, ctype_methods}, {Py_tp_init, PyCFuncPtrType_init}, {0, NULL}, }; diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index 591bbce5185209..c93de188105f5a 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -2017,7 +2017,7 @@ create_pointer_inst(PyObject *module, PyObject *arg) return NULL; } if (typ == NULL) { - typ = create_pointer_type(NULL, (PyObject *)Py_TYPE(arg)); + typ = create_pointer_type(module, (PyObject *)Py_TYPE(arg)); if (typ == NULL) return NULL; } From 0cc59061e225b94c17df1e376b4db733590c9e1e Mon Sep 17 00:00:00 2001 From: neonene Date: Fri, 22 Mar 2024 13:16:50 +0900 Subject: [PATCH 4/9] add missing static --- Modules/_ctypes/_ctypes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index fc2f5e7803b44e..113fee78ca2fb3 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5740,7 +5740,7 @@ static PyModuleDef_Slot module_slots[] = { {0, NULL} }; -struct PyModuleDef _ctypesmodule = { +static struct PyModuleDef _ctypesmodule = { PyModuleDef_HEAD_INIT, .m_name = "_ctypes", .m_doc = _ctypes__doc__, From c5404b6433027446e17b068ee10c68ce5933fbde Mon Sep 17 00:00:00 2001 From: neonene Date: Sun, 24 Mar 2024 01:29:47 +0900 Subject: [PATCH 5/9] revert --- Modules/_ctypes/_ctypes.c | 286 +++++++++++++++---------------------- Modules/_ctypes/callproc.c | 33 +++-- Modules/_ctypes/ctypes.h | 15 +- 3 files changed, 134 insertions(+), 200 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 113fee78ca2fb3..f770047ae57d8d 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -128,6 +128,16 @@ bytes(cdata) ctypes_state global_state = {0}; +PyObject *PyExc_ArgError = NULL; + +/* This dict maps ctypes types to POINTER types */ +PyObject *_ctypes_ptrtype_cache = NULL; + +/* a callable object used for unpickling: + strong reference to _ctypes._unpickle() function */ +static PyObject *_unpickle; + + /****************************************************************/ typedef struct { @@ -537,6 +547,35 @@ CType_Type_sizeof(PyObject *self) return PyLong_FromSsize_t(size); } +static PyObject * +CType_Type_repeat(PyObject *self, Py_ssize_t length); + + +static PyMethodDef ctype_methods[] = { + {"__sizeof__", _PyCFunction_CAST(CType_Type_sizeof), + METH_NOARGS, PyDoc_STR("Return memory consumption of the type object.")}, + {0}, +}; + +static PyType_Slot ctype_type_slots[] = { + {Py_tp_traverse, CType_Type_traverse}, + {Py_tp_clear, CType_Type_clear}, + {Py_tp_dealloc, CType_Type_dealloc}, + {Py_tp_methods, ctype_methods}, + // Sequence protocol. + {Py_sq_repeat, CType_Type_repeat}, + {0, NULL}, +}; + +static PyType_Spec pyctype_type_spec = { + .name = "_ctypes.CType_Type", + .basicsize = -(Py_ssize_t)sizeof(StgInfo), + .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | + Py_TPFLAGS_HAVE_GC | + Py_TPFLAGS_BASETYPE ), + .slots = ctype_type_slots, +}; + /* PyCStructType_Type - a meta type/class. Creating a new class using this one as __metaclass__ will call the constructor StructUnionType_new. @@ -686,7 +725,7 @@ PyDoc_STRVAR(from_address_doc, "C.from_address(integer) -> C instance\naccess a C instance at the specified address"); static PyObject * -CTypeType_from_address(PyObject *type, PyObject *value) +CDataType_from_address(PyObject *type, PyObject *value) { void *buf; if (!PyLong_Check(value)) { @@ -707,7 +746,7 @@ static int KeepRef(CDataObject *target, Py_ssize_t index, PyObject *keep); static PyObject * -CTypeType_from_buffer(PyObject *type, PyObject *args) +CDataType_from_buffer(PyObject *type, PyObject *args) { PyObject *obj; PyObject *mv; @@ -791,7 +830,7 @@ static PyObject * GenericPyCData_new(PyTypeObject *type, PyObject *args, PyObject *kwds); static PyObject * -CTypeType_from_buffer_copy(PyObject *type, PyObject *args) +CDataType_from_buffer_copy(PyObject *type, PyObject *args) { Py_buffer buffer; Py_ssize_t offset = 0; @@ -844,7 +883,7 @@ PyDoc_STRVAR(in_dll_doc, "C.in_dll(dll, name) -> C instance\naccess a C instance in a dll"); static PyObject * -CTypeType_in_dll(PyObject *type, PyObject *args) +CDataType_in_dll(PyObject *type, PyObject *args) { PyObject *dll; char *name; @@ -906,7 +945,7 @@ PyDoc_STRVAR(from_param_doc, "Convert a Python object into a function call parameter."); static PyObject * -CTypeType_from_param(PyObject *type, PyObject *value) +CDataType_from_param(PyObject *type, PyObject *value) { PyObject *as_parameter; int res = PyObject_IsInstance(value, type); @@ -945,7 +984,7 @@ CTypeType_from_param(PyObject *type, PyObject *value) return NULL; } if (as_parameter) { - value = CTypeType_from_param(type, as_parameter); + value = CDataType_from_param(type, as_parameter); Py_DECREF(as_parameter); return value; } @@ -956,8 +995,17 @@ CTypeType_from_param(PyObject *type, PyObject *value) return NULL; } +static PyMethodDef CDataType_methods[] = { + { "from_param", CDataType_from_param, METH_O, from_param_doc }, + { "from_address", CDataType_from_address, METH_O, from_address_doc }, + { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, + { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc }, + { NULL, NULL }, +}; + static PyObject * -CTypeType_repeat(PyObject *self, Py_ssize_t length) +CType_Type_repeat(PyObject *self, Py_ssize_t length) { if (length < 0) return PyErr_Format(PyExc_ValueError, @@ -966,38 +1014,6 @@ CTypeType_repeat(PyObject *self, Py_ssize_t length) return PyCArrayType_from_ctype(self, length); } -static PyMethodDef ctype_methods[] = { - {"__sizeof__", _PyCFunction_CAST(CType_Type_sizeof), - METH_NOARGS, PyDoc_STR("Return memory consumption of the type object.")}, - { "from_param", CTypeType_from_param, METH_O, from_param_doc }, - { "from_address", CTypeType_from_address, METH_O, from_address_doc }, - { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc }, - { NULL, NULL }, -}; - -static PyType_Slot ctype_type_slots[] = { - {Py_tp_traverse, CType_Type_traverse}, - {Py_tp_clear, CType_Type_clear}, - {Py_tp_dealloc, CType_Type_dealloc}, - {Py_tp_methods, ctype_methods}, - - // Sequence protocol. - {Py_sq_repeat, CTypeType_repeat}, - {0, NULL}, -}; - -static PyType_Spec pyctype_type_spec = { - .name = "_ctypes.CType_Type", - .basicsize = -(Py_ssize_t)sizeof(StgInfo), - .flags = (Py_TPFLAGS_DEFAULT | Py_TPFLAGS_IMMUTABLETYPE | - Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE ), - .slots = ctype_type_slots, -}; - - static int PyCStructType_setattro(PyObject *self, PyObject *key, PyObject *value) { @@ -1028,7 +1044,7 @@ UnionType_setattro(PyObject *self, PyObject *key, PyObject *value) static PyType_Slot pycstruct_type_slots[] = { {Py_tp_setattro, PyCStructType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the CData Objects")}, - {Py_tp_methods, ctype_methods}, + {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCStructType_init}, {0, NULL}, }; @@ -1043,7 +1059,7 @@ static PyType_Spec pycstruct_type_spec = { static PyType_Slot union_type_slots[] = { {Py_tp_setattro, UnionType_setattro}, {Py_tp_doc, PyDoc_STR("metatype for the Union Objects")}, - {Py_tp_methods, ctype_methods}, + {Py_tp_methods, CDataType_methods}, {Py_tp_init, UnionType_init}, {0, NULL}, }; @@ -1262,14 +1278,14 @@ PyCPointerType_from_param(PyObject *type, PyObject *value) return Py_NewRef(value); } } - return CTypeType_from_param(type, value); + return CDataType_from_param(type, value); } static PyMethodDef PyCPointerType_methods[] = { - { "from_address", CTypeType_from_address, METH_O, from_address_doc }, - { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc}, + { "from_address", CDataType_from_address, METH_O, from_address_doc }, + { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, + { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, { "from_param", (PyCFunction)PyCPointerType_from_param, METH_O, from_param_doc}, { "set_type", (PyCFunction)PyCPointerType_set_type, METH_O }, { NULL, NULL }, @@ -1607,7 +1623,7 @@ PyCArrayType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycarray_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for the Array Objects")}, - {Py_tp_methods, ctype_methods}, + {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCArrayType_init}, {0, NULL}, }; @@ -1932,26 +1948,25 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject PyObject *name = PyTuple_GET_ITEM(args, 0); PyObject *newname; PyObject *swapped_args; + static PyObject *suffix; Py_ssize_t i; swapped_args = PyTuple_New(PyTuple_GET_SIZE(args)); if (!swapped_args) return NULL; - ctypes_state *st = GLOBAL_STATE(); - if (st->swapped_suffix == NULL) { + if (suffix == NULL) #ifdef WORDS_BIGENDIAN - st->swapped_suffix = PyUnicode_InternFromString("_le"); + suffix = PyUnicode_InternFromString("_le"); #else - st->swapped_suffix = PyUnicode_InternFromString("_be"); + suffix = PyUnicode_InternFromString("_be"); #endif - } - if (st->swapped_suffix == NULL) { + if (suffix == NULL) { Py_DECREF(swapped_args); return NULL; } - newname = PyUnicode_Concat(name, st->swapped_suffix); + newname = PyUnicode_Concat(name, suffix); if (newname == NULL) { Py_DECREF(swapped_args); return NULL; @@ -1971,6 +1986,8 @@ static PyObject *CreateSwappedType(PyTypeObject *type, PyObject *args, PyObject if (result == NULL) return NULL; + ctypes_state *st = GLOBAL_STATE(); + StgInfo *stginfo = PyStgInfo_Init(st, result); if (!stginfo) { Py_DECREF(result); @@ -2266,10 +2283,10 @@ PyCSimpleType_from_param(PyObject *type, PyObject *value) static PyMethodDef PyCSimpleType_methods[] = { { "from_param", PyCSimpleType_from_param, METH_O, from_param_doc }, - { "from_address", CTypeType_from_address, METH_O, from_address_doc }, - { "from_buffer", CTypeType_from_buffer, METH_VARARGS, from_buffer_doc, }, - { "from_buffer_copy", CTypeType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, - { "in_dll", CTypeType_in_dll, METH_VARARGS, in_dll_doc}, + { "from_address", CDataType_from_address, METH_O, from_address_doc }, + { "from_buffer", CDataType_from_buffer, METH_VARARGS, from_buffer_doc, }, + { "from_buffer_copy", CDataType_from_buffer_copy, METH_VARARGS, from_buffer_copy_doc, }, + { "in_dll", CDataType_in_dll, METH_VARARGS, in_dll_doc}, { NULL, NULL }, }; @@ -2308,8 +2325,7 @@ converters_from_argtypes(PyObject *ob) Py_ssize_t nArgs = PyTuple_GET_SIZE(ob); if (nArgs > CTYPES_MAX_ARGCOUNT) { Py_DECREF(ob); - ctypes_state *st = GLOBAL_STATE(); - PyErr_Format(st->PyExc_ArgError, + PyErr_Format(PyExc_ArgError, "_argtypes_ has too many arguments (%zi), maximum is %i", nArgs, CTYPES_MAX_ARGCOUNT); return NULL; @@ -2529,7 +2545,7 @@ PyCFuncPtrType_init(PyObject *self, PyObject *args, PyObject *kwds) static PyType_Slot pycfuncptr_type_slots[] = { {Py_tp_doc, PyDoc_STR("metatype for C function pointers")}, - {Py_tp_methods, ctype_methods}, + {Py_tp_methods, CDataType_methods}, {Py_tp_init, PyCFuncPtrType_init}, {0, NULL}, }; @@ -2789,7 +2805,7 @@ PyCData_reduce(PyObject *myself, PyObject *args) if (dict == NULL) { return NULL; } - return Py_BuildValue("O(O(NN))", st->_unpickle, Py_TYPE(myself), dict, + return Py_BuildValue("O(O(NN))", _unpickle, Py_TYPE(myself), dict, PyBytes_FromStringAndSize(self->b_ptr, self->b_size)); } @@ -4737,14 +4753,14 @@ static PyType_Spec pycarray_spec = { PyObject * PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) { + static PyObject *cache; PyObject *key; char name[256]; PyObject *len; - ctypes_state *st = GLOBAL_STATE(); - if (st->array_cache == NULL) { - st->array_cache = PyDict_New(); - if (st->array_cache == NULL) + if (cache == NULL) { + cache = PyDict_New(); + if (cache == NULL) return NULL; } len = PyLong_FromSsize_t(length); @@ -4756,7 +4772,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) return NULL; PyObject *result; - if (_PyDict_GetItemProxy(st->array_cache, key, &result) != 0) { + if (_PyDict_GetItemProxy(cache, key, &result) != 0) { // found or error Py_DECREF(key); return result; @@ -4775,6 +4791,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) sprintf(name, "%.200s_Array_%ld", ((PyTypeObject *)itemtype)->tp_name, (long)length); #endif + ctypes_state *st = GLOBAL_STATE(); result = PyObject_CallFunction((PyObject *)st->PyCArrayType_Type, "s(O){s:n,s:O}", name, @@ -4788,7 +4805,7 @@ PyCArrayType_from_ctype(PyObject *itemtype, Py_ssize_t length) Py_DECREF(key); return NULL; } - if (PyDict_SetItemProxy(st->array_cache, key, result) < 0) { + if (-1 == PyDict_SetItemProxy(cache, key, result)) { Py_DECREF(key); Py_DECREF(result); return NULL; @@ -5480,6 +5497,15 @@ wstring_at(const wchar_t *ptr, int size) } +static struct PyModuleDef _ctypesmodule = { + PyModuleDef_HEAD_INIT, + .m_name = "_ctypes", + .m_doc = _ctypes__doc__, + .m_size = -1, + .m_methods = _ctypes_module_methods, +}; + + static int _ctypes_add_types(PyObject *mod) { @@ -5588,10 +5614,10 @@ _ctypes_add_objects(PyObject *mod) } \ } while (0) - ctypes_state *st = GLOBAL_STATE(); - MOD_ADD("_pointer_type_cache", Py_NewRef(st->_ctypes_ptrtype_cache)); + MOD_ADD("_pointer_type_cache", Py_NewRef(_ctypes_ptrtype_cache)); #ifdef MS_WIN32 + ctypes_state *st = GLOBAL_STATE(); MOD_ADD("COMError", Py_NewRef(st->PyComError_Type)); MOD_ADD("FUNCFLAG_HRESULT", PyLong_FromLong(FUNCFLAG_HRESULT)); MOD_ADD("FUNCFLAG_STDCALL", PyLong_FromLong(FUNCFLAG_STDCALL)); @@ -5621,7 +5647,7 @@ _ctypes_add_objects(PyObject *mod) MOD_ADD("RTLD_LOCAL", PyLong_FromLong(RTLD_LOCAL)); MOD_ADD("RTLD_GLOBAL", PyLong_FromLong(RTLD_GLOBAL)); MOD_ADD("CTYPES_MAX_ARGCOUNT", PyLong_FromLong(CTYPES_MAX_ARGCOUNT)); - MOD_ADD("ArgumentError", Py_NewRef(st->PyExc_ArgError)); + MOD_ADD("ArgumentError", Py_NewRef(PyExc_ArgError)); MOD_ADD("SIZEOF_TIME_T", PyLong_FromSsize_t(SIZEOF_TIME_T)); return 0; #undef MOD_ADD @@ -5631,19 +5657,18 @@ _ctypes_add_objects(PyObject *mod) static int _ctypes_mod_exec(PyObject *mod) { - ctypes_state *st = GLOBAL_STATE(); - st->_unpickle = PyObject_GetAttrString(mod, "_unpickle"); - if (st->_unpickle == NULL) { + _unpickle = PyObject_GetAttrString(mod, "_unpickle"); + if (_unpickle == NULL) { return -1; } - st->_ctypes_ptrtype_cache = PyDict_New(); - if (st->_ctypes_ptrtype_cache == NULL) { + _ctypes_ptrtype_cache = PyDict_New(); + if (_ctypes_ptrtype_cache == NULL) { return -1; } - st->PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); - if (!st->PyExc_ArgError) { + PyExc_ArgError = PyErr_NewException("ctypes.ArgumentError", NULL, NULL); + if (!PyExc_ArgError) { return -1; } @@ -5658,104 +5683,19 @@ _ctypes_mod_exec(PyObject *mod) } -static int -module_traverse(PyObject *module, visitproc visit, void *arg) { - ctypes_state *st = GLOBAL_STATE(); - Py_VISIT(st->_ctypes_ptrtype_cache); - Py_VISIT(st->_unpickle); - Py_VISIT(st->array_cache); - Py_VISIT(st->error_object_name); - Py_VISIT(st->PyExc_ArgError); - Py_VISIT(st->swapped_suffix); - - Py_VISIT(st->DictRemover_Type); - Py_VISIT(st->PyCArg_Type); - Py_VISIT(st->PyCField_Type); - Py_VISIT(st->PyCThunk_Type); - Py_VISIT(st->StructParam_Type); - Py_VISIT(st->PyCStructType_Type); - Py_VISIT(st->UnionType_Type); - Py_VISIT(st->PyCPointerType_Type); - Py_VISIT(st->PyCArrayType_Type); - Py_VISIT(st->PyCSimpleType_Type); - Py_VISIT(st->PyCFuncPtrType_Type); - Py_VISIT(st->PyCData_Type); - Py_VISIT(st->Struct_Type); - Py_VISIT(st->Union_Type); - Py_VISIT(st->PyCArray_Type); - Py_VISIT(st->Simple_Type); - Py_VISIT(st->PyCPointer_Type); - Py_VISIT(st->PyCFuncPtr_Type); -#ifdef MS_WIN32 - Py_VISIT(st->PyComError_Type); -#endif - Py_VISIT(st->PyCType_Type); - return 0; -} - -static int -module_clear(PyObject *module) { - ctypes_state *st = GLOBAL_STATE(); - Py_CLEAR(st->_ctypes_ptrtype_cache); - Py_CLEAR(st->_unpickle); - Py_CLEAR(st->array_cache); - Py_CLEAR(st->error_object_name); - Py_CLEAR(st->PyExc_ArgError); - Py_CLEAR(st->swapped_suffix); - - Py_CLEAR(st->DictRemover_Type); - Py_CLEAR(st->PyCArg_Type); - Py_CLEAR(st->PyCField_Type); - Py_CLEAR(st->PyCThunk_Type); - Py_CLEAR(st->StructParam_Type); - Py_CLEAR(st->PyCStructType_Type); - Py_CLEAR(st->UnionType_Type); - Py_CLEAR(st->PyCPointerType_Type); - Py_CLEAR(st->PyCArrayType_Type); - Py_CLEAR(st->PyCSimpleType_Type); - Py_CLEAR(st->PyCFuncPtrType_Type); - Py_CLEAR(st->PyCData_Type); - Py_CLEAR(st->Struct_Type); - Py_CLEAR(st->Union_Type); - Py_CLEAR(st->PyCArray_Type); - Py_CLEAR(st->Simple_Type); - Py_CLEAR(st->PyCPointer_Type); - Py_CLEAR(st->PyCFuncPtr_Type); -#ifdef MS_WIN32 - Py_CLEAR(st->PyComError_Type); -#endif - Py_CLEAR(st->PyCType_Type); - return 0; -} - -static void -module_free(void *module) -{ - (void)module_clear((PyObject *)module); -} - -static PyModuleDef_Slot module_slots[] = { - {Py_mod_exec, _ctypes_mod_exec}, - // {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED}, - {0, NULL} -}; - -static struct PyModuleDef _ctypesmodule = { - PyModuleDef_HEAD_INIT, - .m_name = "_ctypes", - .m_doc = _ctypes__doc__, - .m_size = 0, - .m_methods = _ctypes_module_methods, - .m_slots = module_slots, - .m_traverse = module_traverse, - .m_clear = module_clear, - .m_free = module_free, -}; - PyMODINIT_FUNC PyInit__ctypes(void) { - return PyModuleDef_Init(&_ctypesmodule); + PyObject *mod = PyModule_Create(&_ctypesmodule); + if (!mod) { + return NULL; + } + + if (_ctypes_mod_exec(mod) < 0) { + Py_DECREF(mod); + return NULL; + } + return mod; } /* diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index c93de188105f5a..6ebbb64d61b07a 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -157,18 +157,18 @@ _ctypes_get_errobj(int **pspace) { PyObject *dict = PyThreadState_GetDict(); PyObject *errobj; + static PyObject *error_object_name; if (dict == NULL) { PyErr_SetString(PyExc_RuntimeError, "cannot get thread state"); return NULL; } - ctypes_state *st = GLOBAL_STATE(); - if (st->error_object_name == NULL) { - st->error_object_name = PyUnicode_InternFromString("ctypes.error_object"); - if (st->error_object_name == NULL) + if (error_object_name == NULL) { + error_object_name = PyUnicode_InternFromString("ctypes.error_object"); + if (error_object_name == NULL) return NULL; } - if (PyDict_GetItemRef(dict, st->error_object_name, &errobj) < 0) { + if (PyDict_GetItemRef(dict, error_object_name, &errobj) < 0) { return NULL; } if (errobj) { @@ -188,7 +188,8 @@ _ctypes_get_errobj(int **pspace) PyMem_Free(space); return NULL; } - if (PyDict_SetItem(dict, st->error_object_name, errobj) < 0) { + if (-1 == PyDict_SetItem(dict, error_object_name, + errobj)) { Py_DECREF(errobj); return NULL; } @@ -1196,10 +1197,9 @@ PyObject *_ctypes_callproc(PPROC pProc, ++argcount; #endif - ctypes_state *st = GLOBAL_STATE(); if (argcount > CTYPES_MAX_ARGCOUNT) { - PyErr_Format(st->PyExc_ArgError, "too many arguments (%zi), maximum is %i", + PyErr_Format(PyExc_ArgError, "too many arguments (%zi), maximum is %i", argcount, CTYPES_MAX_ARGCOUNT); return NULL; } @@ -1232,20 +1232,20 @@ PyObject *_ctypes_callproc(PPROC pProc, converter = PyTuple_GET_ITEM(argtypes, i); v = PyObject_CallOneArg(converter, arg); if (v == NULL) { - _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; } err = ConvParam(v, i+1, pa); Py_DECREF(v); if (-1 == err) { - _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; } } else { err = ConvParam(arg, i+1, pa); if (-1 == err) { - _ctypes_extend_error(st->PyExc_ArgError, "argument %zd: ", i+1); + _ctypes_extend_error(PyExc_ArgError, "argument %zd: ", i+1); goto cleanup; /* leaking ? */ } } @@ -1949,11 +1949,11 @@ create_pointer_type(PyObject *module, PyObject *cls) PyTypeObject *typ; PyObject *key; - ctypes_state *st = GLOBAL_STATE(); - if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, cls, &result) != 0) { + if (PyDict_GetItemRef(_ctypes_ptrtype_cache, cls, &result) != 0) { // found or error return result; } + ctypes_state *st = GLOBAL_STATE(); // not found if (PyUnicode_CheckExact(cls)) { PyObject *name = PyUnicode_FromFormat("LP_%U", cls); @@ -1983,7 +1983,7 @@ create_pointer_type(PyObject *module, PyObject *cls) PyErr_SetString(PyExc_TypeError, "must be a ctypes type"); return NULL; } - if (PyDict_SetItem(st->_ctypes_ptrtype_cache, key, result) < 0) { + if (-1 == PyDict_SetItem(_ctypes_ptrtype_cache, key, result)) { Py_DECREF(result); Py_DECREF(key); return NULL; @@ -2012,12 +2012,11 @@ create_pointer_inst(PyObject *module, PyObject *arg) PyObject *result; PyObject *typ; - ctypes_state *st = GLOBAL_STATE(); - if (PyDict_GetItemRef(st->_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { + if (PyDict_GetItemRef(_ctypes_ptrtype_cache, (PyObject *)Py_TYPE(arg), &typ) < 0) { return NULL; } if (typ == NULL) { - typ = create_pointer_type(module, (PyObject *)Py_TYPE(arg)); + typ = create_pointer_type(NULL, (PyObject *)Py_TYPE(arg)); if (typ == NULL) return NULL; } diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index a10daf06540376..d7d725a4fdf669 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -42,7 +42,6 @@ typedef struct { PyTypeObject *PyCField_Type; PyTypeObject *PyCThunk_Type; PyTypeObject *StructParam_Type; - PyTypeObject *PyCType_Type; PyTypeObject *PyCStructType_Type; PyTypeObject *UnionType_Type; PyTypeObject *PyCPointerType_Type; @@ -59,15 +58,7 @@ typedef struct { #ifdef MS_WIN32 PyTypeObject *PyComError_Type; #endif - /* This dict maps ctypes types to POINTER types */ - PyObject *_ctypes_ptrtype_cache; - /* a callable object used for unpickling: - strong reference to _ctypes._unpickle() function */ - PyObject *_unpickle; - PyObject *array_cache; - PyObject *error_object_name; // callproc.c - PyObject *PyExc_ArgError; - PyObject *swapped_suffix; + PyTypeObject *PyCType_Type; } ctypes_state; extern ctypes_state global_state; @@ -384,6 +375,9 @@ extern char basespec_string[]; extern ffi_type *_ctypes_get_ffi_type(PyObject *obj); +/* exception classes */ +extern PyObject *PyExc_ArgError; + extern char *_ctypes_conversion_encoding; extern char *_ctypes_conversion_errors; @@ -399,6 +393,7 @@ extern char *_ctypes_alloc_format_string_with_shape(int ndim, extern int _ctypes_simple_instance(PyObject *obj); +extern PyObject *_ctypes_ptrtype_cache; PyObject *_ctypes_get_errobj(int **pspace); #ifdef USING_MALLOC_CLOSURE_DOT_C From aa676e2be3d73cd4b28fa56b41c92db0886431a7 Mon Sep 17 00:00:00 2001 From: neonene Date: Sun, 24 Mar 2024 01:34:47 +0900 Subject: [PATCH 6/9] revert tsv --- Tools/c-analyzer/cpython/globals-to-fix.tsv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv index 65f94e50e1bd7d..92fab9b3998636 100644 --- a/Tools/c-analyzer/cpython/globals-to-fix.tsv +++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv @@ -416,14 +416,14 @@ Modules/xxmodule.c - ErrorObject - ## manually cached PyUnicodeOjbect Modules/_ctypes/callproc.c _ctypes_get_errobj error_object_name - -Modules/_ctypes/_ctypes.c CreateSwappedType swapped_suffix - +Modules/_ctypes/_ctypes.c CreateSwappedType suffix - ##----------------------- ## other ## initialized once Modules/_ctypes/_ctypes.c - _unpickle - -Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype array_cache - +Modules/_ctypes/_ctypes.c PyCArrayType_from_ctype cache - Modules/_cursesmodule.c - ModDict - Modules/_datetimemodule.c datetime_strptime module - From f3881e6b13691c04835c350ae17ffbf58769130c Mon Sep 17 00:00:00 2001 From: neonene Date: Tue, 26 Mar 2024 07:25:07 +0900 Subject: [PATCH 7/9] no return on err (traverse, clear) --- Modules/_ctypes/_ctypes.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index f770047ae57d8d..b67af824aeb190 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -451,13 +451,11 @@ static PyType_Spec structparam_spec = { static int CType_Type_traverse(PyObject *self, visitproc visit, void *arg) { - Py_VISIT(Py_TYPE(self)); - ctypes_state *st = GLOBAL_STATE(); if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { - return -1; + PyErr_WriteUnraisable(self); } if (info) { Py_VISIT(info->proto); @@ -467,6 +465,7 @@ CType_Type_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(info->checker); } } + Py_VISIT(Py_TYPE(self)); return PyType_Type.tp_traverse(self, visit, arg); } @@ -488,7 +487,7 @@ CType_Type_clear(PyObject *self) if (st && st->PyCType_Type) { StgInfo *info; if (PyStgInfo_FromType(st, self, &info) < 0) { - return -1; + PyErr_WriteUnraisable(self); } if (info) { _ctype_clear_stginfo(info); From 449b3bba1d7ef28c632a798a3d2efefe70cf8917 Mon Sep 17 00:00:00 2001 From: neonene Date: Tue, 26 Mar 2024 07:45:45 +0900 Subject: [PATCH 8/9] restore Py_CLEAR() in PyCStgInfo_clone() --- Modules/_ctypes/_ctypes.c | 8 ++++---- Modules/_ctypes/ctypes.h | 1 + Modules/_ctypes/stgdict.c | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index b67af824aeb190..50664df874ea51 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -469,8 +469,8 @@ CType_Type_traverse(PyObject *self, visitproc visit, void *arg) return PyType_Type.tp_traverse(self, visit, arg); } -static void -_ctype_clear_stginfo(StgInfo *info) +void +ctype_clear_stginfo(StgInfo *info) { assert(info); Py_CLEAR(info->proto); @@ -490,7 +490,7 @@ CType_Type_clear(PyObject *self) PyErr_WriteUnraisable(self); } if (info) { - _ctype_clear_stginfo(info); + ctype_clear_stginfo(info); } } return PyType_Type.tp_clear(self); @@ -513,7 +513,7 @@ CType_Type_dealloc(PyObject *self) info->format = NULL; PyMem_Free(info->shape); info->shape = NULL; - _ctype_clear_stginfo(info); + ctype_clear_stginfo(info); } } diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index d7d725a4fdf669..a82f26647ac43c 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -303,6 +303,7 @@ typedef struct { } StgInfo; extern int PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info); +extern void ctype_clear_stginfo(StgInfo *info); typedef int(* PPROC)(void); diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index 8666ded5c2b3f2..ce4baf88220cfe 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -25,6 +25,7 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info) { Py_ssize_t size; + ctype_clear_stginfo(dst_info); PyMem_Free(dst_info->ffi_type_pointer.elements); PyMem_Free(dst_info->format); dst_info->format = NULL; From db8449472a2406b597ee36e58a67409f600c336f Mon Sep 17 00:00:00 2001 From: neonene Date: Tue, 26 Mar 2024 08:16:20 +0900 Subject: [PATCH 9/9] Avoid module_free() until infos are cleard --- Modules/_ctypes/_ctypes.c | 2 ++ Modules/_ctypes/ctypes.h | 7 +++++++ Modules/_ctypes/stgdict.c | 1 + 3 files changed, 10 insertions(+) diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index 50664df874ea51..5dc943fa6f5557 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -463,6 +463,7 @@ CType_Type_traverse(PyObject *self, visitproc visit, void *arg) Py_VISIT(info->converters); Py_VISIT(info->restype); Py_VISIT(info->checker); + Py_VISIT(info->module); } } Py_VISIT(Py_TYPE(self)); @@ -478,6 +479,7 @@ ctype_clear_stginfo(StgInfo *info) Py_CLEAR(info->converters); Py_CLEAR(info->restype); Py_CLEAR(info->checker); + Py_CLEAR(info->module); } static int diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index a82f26647ac43c..311d969f3f4191 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -292,6 +292,7 @@ typedef struct { PyObject *converters; /* tuple([t.from_param for t in argtypes]) */ PyObject *restype; /* CDataObject or NULL */ PyObject *checker; + PyObject *module; int flags; /* calling convention and such */ /* pep3118 fields, pointers need PyMem_Free */ @@ -473,6 +474,12 @@ PyStgInfo_Init(ctypes_state *state, PyTypeObject *type) type->tp_name); return NULL; } + PyObject *module = PyType_GetModule(state->PyCType_Type); + if (!module) { + return NULL; + } + info->module = Py_NewRef(module); + info->initialized = 1; return info; } diff --git a/Modules/_ctypes/stgdict.c b/Modules/_ctypes/stgdict.c index ce4baf88220cfe..65a5bb8403a831 100644 --- a/Modules/_ctypes/stgdict.c +++ b/Modules/_ctypes/stgdict.c @@ -40,6 +40,7 @@ PyCStgInfo_clone(StgInfo *dst_info, StgInfo *src_info) Py_XINCREF(dst_info->converters); Py_XINCREF(dst_info->restype); Py_XINCREF(dst_info->checker); + Py_XINCREF(dst_info->module); if (src_info->format) { dst_info->format = PyMem_Malloc(strlen(src_info->format) + 1);