From d2ec81a8c99796b51fb8c49b77a7fe369863226f Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Fri, 7 Feb 2020 09:17:07 +0100 Subject: [PATCH] bpo-39573: Add Py_SET_TYPE() function (GH-18394) Add Py_SET_TYPE() function to set the type of an object. --- Doc/c-api/structures.rst | 7 +++++++ Include/cpython/objimpl.h | 2 +- Include/object.h | 6 ++++++ .../C API/2020-02-07-03-39-03.bpo-39573.Oa8cL1.rst | 1 + Modules/_blake2/blake2module.c | 4 ++-- Modules/_ctypes/_ctypes.c | 12 ++++++------ Modules/_ctypes/ctypes.h | 2 +- Modules/_sha3/sha3module.c | 2 +- Modules/_sqlite/prepare_protocol.c | 2 +- Modules/_testbuffer.c | 4 ++-- Modules/_testcapimodule.c | 4 ++-- Modules/arraymodule.c | 2 +- Modules/itertoolsmodule.c | 8 +++++--- Modules/md5module.c | 8 +++++--- Modules/sha1module.c | 8 +++++--- Modules/sha256module.c | 10 ++++++---- Modules/sha512module.c | 13 ++++++++----- Modules/socketmodule.c | 2 +- Modules/unicodedata.c | 2 +- Objects/floatobject.c | 2 +- Objects/moduleobject.c | 2 +- Objects/object.c | 2 +- Objects/typeobject.c | 10 ++++++---- Objects/weakrefobject.c | 10 ++++++---- 24 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 Misc/NEWS.d/next/C API/2020-02-07-03-39-03.bpo-39573.Oa8cL1.rst diff --git a/Doc/c-api/structures.rst b/Doc/c-api/structures.rst index 100573c5693..8a1431c2de7 100644 --- a/Doc/c-api/structures.rst +++ b/Doc/c-api/structures.rst @@ -70,6 +70,13 @@ the definition of all other Python objects. (((PyObject*)(o))->ob_type) +.. c:function:: void Py_SET_TYPE(PyObject *o, PyTypeObject *type) + + Set the object *o* type to *type*. + + .. versionadded:: 3.9 + + .. c:macro:: Py_REFCNT(o) This macro is used to access the :attr:`ob_refcnt` member of a Python diff --git a/Include/cpython/objimpl.h b/Include/cpython/objimpl.h index 3f148146f67..ebb3e234e36 100644 --- a/Include/cpython/objimpl.h +++ b/Include/cpython/objimpl.h @@ -15,7 +15,7 @@ static inline PyObject* _PyObject_INIT(PyObject *op, PyTypeObject *typeobj) { assert(op != NULL); - Py_TYPE(op) = typeobj; + Py_SET_TYPE(op, typeobj); if (PyType_GetFlags(typeobj) & Py_TPFLAGS_HEAPTYPE) { Py_INCREF(typeobj); } diff --git a/Include/object.h b/Include/object.h index 0b630513375..eb887f4c6eb 100644 --- a/Include/object.h +++ b/Include/object.h @@ -128,6 +128,12 @@ static inline void _Py_SET_REFCNT(PyObject *ob, Py_ssize_t refcnt) { } #define Py_SET_REFCNT(ob, refcnt) _Py_SET_REFCNT(_PyObject_CAST(ob), refcnt) +static inline void _Py_SET_TYPE(PyObject *ob, PyTypeObject *type) { + ob->ob_type = type; +} +#define Py_SET_TYPE(ob, type) _Py_SET_TYPE(_PyObject_CAST(ob), type) + + /* Type objects contain a string containing the type name (to help somewhat in debugging), the allocation parameters (see PyObject_New() and diff --git a/Misc/NEWS.d/next/C API/2020-02-07-03-39-03.bpo-39573.Oa8cL1.rst b/Misc/NEWS.d/next/C API/2020-02-07-03-39-03.bpo-39573.Oa8cL1.rst new file mode 100644 index 00000000000..22d3d693ac0 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2020-02-07-03-39-03.bpo-39573.Oa8cL1.rst @@ -0,0 +1 @@ +Add :c:func:`Py_SET_TYPE` function to set the type of an object. diff --git a/Modules/_blake2/blake2module.c b/Modules/_blake2/blake2module.c index e2a3d420d4e..9d280a9ccd5 100644 --- a/Modules/_blake2/blake2module.c +++ b/Modules/_blake2/blake2module.c @@ -62,7 +62,7 @@ PyInit__blake2(void) return NULL; /* BLAKE2b */ - Py_TYPE(&PyBlake2_BLAKE2bType) = &PyType_Type; + Py_SET_TYPE(&PyBlake2_BLAKE2bType, &PyType_Type); if (PyType_Ready(&PyBlake2_BLAKE2bType) < 0) { return NULL; } @@ -82,7 +82,7 @@ PyInit__blake2(void) PyModule_AddIntConstant(m, "BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES); /* BLAKE2s */ - Py_TYPE(&PyBlake2_BLAKE2sType) = &PyType_Type; + Py_SET_TYPE(&PyBlake2_BLAKE2sType, &PyType_Type); if (PyType_Ready(&PyBlake2_BLAKE2sType) < 0) { return NULL; } diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c index cb6e03f2ca1..4747195c2e6 100644 --- a/Modules/_ctypes/_ctypes.c +++ b/Modules/_ctypes/_ctypes.c @@ -5758,42 +5758,42 @@ PyInit__ctypes(void) if (PyType_Ready(&PyCData_Type) < 0) return NULL; - Py_TYPE(&Struct_Type) = &PyCStructType_Type; + Py_SET_TYPE(&Struct_Type, &PyCStructType_Type); Struct_Type.tp_base = &PyCData_Type; if (PyType_Ready(&Struct_Type) < 0) return NULL; Py_INCREF(&Struct_Type); PyModule_AddObject(m, "Structure", (PyObject *)&Struct_Type); - Py_TYPE(&Union_Type) = &UnionType_Type; + Py_SET_TYPE(&Union_Type, &UnionType_Type); Union_Type.tp_base = &PyCData_Type; if (PyType_Ready(&Union_Type) < 0) return NULL; Py_INCREF(&Union_Type); PyModule_AddObject(m, "Union", (PyObject *)&Union_Type); - Py_TYPE(&PyCPointer_Type) = &PyCPointerType_Type; + Py_SET_TYPE(&PyCPointer_Type, &PyCPointerType_Type); PyCPointer_Type.tp_base = &PyCData_Type; if (PyType_Ready(&PyCPointer_Type) < 0) return NULL; Py_INCREF(&PyCPointer_Type); PyModule_AddObject(m, "_Pointer", (PyObject *)&PyCPointer_Type); - Py_TYPE(&PyCArray_Type) = &PyCArrayType_Type; + Py_SET_TYPE(&PyCArray_Type, &PyCArrayType_Type); PyCArray_Type.tp_base = &PyCData_Type; if (PyType_Ready(&PyCArray_Type) < 0) return NULL; Py_INCREF(&PyCArray_Type); PyModule_AddObject(m, "Array", (PyObject *)&PyCArray_Type); - Py_TYPE(&Simple_Type) = &PyCSimpleType_Type; + Py_SET_TYPE(&Simple_Type, &PyCSimpleType_Type); Simple_Type.tp_base = &PyCData_Type; if (PyType_Ready(&Simple_Type) < 0) return NULL; Py_INCREF(&Simple_Type); PyModule_AddObject(m, "_SimpleCData", (PyObject *)&Simple_Type); - Py_TYPE(&PyCFuncPtr_Type) = &PyCFuncPtrType_Type; + Py_SET_TYPE(&PyCFuncPtr_Type, &PyCFuncPtrType_Type); PyCFuncPtr_Type.tp_base = &PyCData_Type; if (PyType_Ready(&PyCFuncPtr_Type) < 0) return NULL; diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 351f996be05..a232a4bc832 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -68,7 +68,7 @@ typedef struct { ffi_type *atypes[1]; } CThunkObject; extern PyTypeObject PyCThunk_Type; -#define CThunk_CheckExact(v) ((v)->ob_type == &PyCThunk_Type) +#define CThunk_CheckExact(v) (Py_TYPE(v) == &PyCThunk_Type) typedef struct { /* First part identical to tagCDataObject */ diff --git a/Modules/_sha3/sha3module.c b/Modules/_sha3/sha3module.c index d4ca9a111da..9cdee5869a2 100644 --- a/Modules/_sha3/sha3module.c +++ b/Modules/_sha3/sha3module.c @@ -713,7 +713,7 @@ PyInit__sha3(void) #define init_sha3type(name, type) \ do { \ - Py_TYPE(type) = &PyType_Type; \ + Py_SET_TYPE(type, &PyType_Type); \ if (PyType_Ready(type) < 0) { \ goto error; \ } \ diff --git a/Modules/_sqlite/prepare_protocol.c b/Modules/_sqlite/prepare_protocol.c index 181c7edf96b..05a2ca5a652 100644 --- a/Modules/_sqlite/prepare_protocol.c +++ b/Modules/_sqlite/prepare_protocol.c @@ -78,6 +78,6 @@ PyTypeObject pysqlite_PrepareProtocolType= { extern int pysqlite_prepare_protocol_setup_types(void) { pysqlite_PrepareProtocolType.tp_new = PyType_GenericNew; - Py_TYPE(&pysqlite_PrepareProtocolType)= &PyType_Type; + Py_SET_TYPE(&pysqlite_PrepareProtocolType, &PyType_Type); return PyType_Ready(&pysqlite_PrepareProtocolType); } diff --git a/Modules/_testbuffer.c b/Modules/_testbuffer.c index 047e3d3974c..600a52aa872 100644 --- a/Modules/_testbuffer.c +++ b/Modules/_testbuffer.c @@ -2835,11 +2835,11 @@ PyInit__testbuffer(void) if (m == NULL) return NULL; - Py_TYPE(&NDArray_Type) = &PyType_Type; + Py_SET_TYPE(&NDArray_Type, &PyType_Type); Py_INCREF(&NDArray_Type); PyModule_AddObject(m, "ndarray", (PyObject *)&NDArray_Type); - Py_TYPE(&StaticArray_Type) = &PyType_Type; + Py_SET_TYPE(&StaticArray_Type, &PyType_Type); Py_INCREF(&StaticArray_Type); PyModule_AddObject(m, "staticarray", (PyObject *)&StaticArray_Type); diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 3bb1bf1e274..e6d30341cdf 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -6605,9 +6605,9 @@ PyInit__testcapi(void) if (m == NULL) return NULL; - Py_TYPE(&_HashInheritanceTester_Type)=&PyType_Type; + Py_SET_TYPE(&_HashInheritanceTester_Type, &PyType_Type); - Py_TYPE(&test_structmembersType)=&PyType_Type; + Py_SET_TYPE(&test_structmembersType, &PyType_Type); Py_INCREF(&test_structmembersType); /* don't use a name starting with "test", since we don't want test_capi to automatically call this */ diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c index edb56ab6e18..5065d28dafb 100644 --- a/Modules/arraymodule.c +++ b/Modules/arraymodule.c @@ -2996,7 +2996,7 @@ array_modexec(PyObject *m) if (PyType_Ready(&Arraytype) < 0) return -1; - Py_TYPE(&PyArrayIter_Type) = &PyType_Type; + Py_SET_TYPE(&PyArrayIter_Type, &PyType_Type); Py_INCREF((PyObject *)&Arraytype); if (PyModule_AddObject(m, "ArrayType", (PyObject *)&Arraytype) < 0) { diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index 0cb472966d1..0dafb65c288 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -4750,14 +4750,16 @@ PyInit_itertools(void) NULL }; - Py_TYPE(&teedataobject_type) = &PyType_Type; + Py_SET_TYPE(&teedataobject_type, &PyType_Type); m = PyModule_Create(&itertoolsmodule); - if (m == NULL) + if (m == NULL) { return NULL; + } for (i=0 ; typelist[i] != NULL ; i++) { - if (PyType_Ready(typelist[i]) < 0) + if (PyType_Ready(typelist[i]) < 0) { return NULL; + } name = _PyType_Name(typelist[i]); Py_INCREF(typelist[i]); PyModule_AddObject(m, name, (PyObject *)typelist[i]); diff --git a/Modules/md5module.c b/Modules/md5module.c index f2c2d32cbe7..d783ae5a765 100644 --- a/Modules/md5module.c +++ b/Modules/md5module.c @@ -572,13 +572,15 @@ PyInit__md5(void) { PyObject *m; - Py_TYPE(&MD5type) = &PyType_Type; - if (PyType_Ready(&MD5type) < 0) + Py_SET_TYPE(&MD5type, &PyType_Type); + if (PyType_Ready(&MD5type) < 0) { return NULL; + } m = PyModule_Create(&_md5module); - if (m == NULL) + if (m == NULL) { return NULL; + } Py_INCREF((PyObject *)&MD5type); PyModule_AddObject(m, "MD5Type", (PyObject *)&MD5type); diff --git a/Modules/sha1module.c b/Modules/sha1module.c index 4d191c3c488..e066b880229 100644 --- a/Modules/sha1module.c +++ b/Modules/sha1module.c @@ -549,13 +549,15 @@ PyInit__sha1(void) { PyObject *m; - Py_TYPE(&SHA1type) = &PyType_Type; - if (PyType_Ready(&SHA1type) < 0) + Py_SET_TYPE(&SHA1type, &PyType_Type); + if (PyType_Ready(&SHA1type) < 0) { return NULL; + } m = PyModule_Create(&_sha1module); - if (m == NULL) + if (m == NULL) { return NULL; + } Py_INCREF((PyObject *)&SHA1type); PyModule_AddObject(m, "SHA1Type", (PyObject *)&SHA1type); diff --git a/Modules/sha256module.c b/Modules/sha256module.c index 245f4c04542..0e0c4461880 100644 --- a/Modules/sha256module.c +++ b/Modules/sha256module.c @@ -713,12 +713,14 @@ PyInit__sha256(void) { PyObject *m; - Py_TYPE(&SHA224type) = &PyType_Type; - if (PyType_Ready(&SHA224type) < 0) + Py_SET_TYPE(&SHA224type, &PyType_Type); + if (PyType_Ready(&SHA224type) < 0) { return NULL; - Py_TYPE(&SHA256type) = &PyType_Type; - if (PyType_Ready(&SHA256type) < 0) + } + Py_SET_TYPE(&SHA256type, &PyType_Type); + if (PyType_Ready(&SHA256type) < 0) { return NULL; + } m = PyModule_Create(&_sha256module); if (m == NULL) diff --git a/Modules/sha512module.c b/Modules/sha512module.c index 4045698387f..07bf2835188 100644 --- a/Modules/sha512module.c +++ b/Modules/sha512module.c @@ -778,16 +778,19 @@ PyInit__sha512(void) { PyObject *m; - Py_TYPE(&SHA384type) = &PyType_Type; - if (PyType_Ready(&SHA384type) < 0) + Py_SET_TYPE(&SHA384type, &PyType_Type); + if (PyType_Ready(&SHA384type) < 0) { return NULL; - Py_TYPE(&SHA512type) = &PyType_Type; - if (PyType_Ready(&SHA512type) < 0) + } + Py_SET_TYPE(&SHA512type, &PyType_Type); + if (PyType_Ready(&SHA512type) < 0) { return NULL; + } m = PyModule_Create(&_sha512module); - if (m == NULL) + if (m == NULL) { return NULL; + } Py_INCREF((PyObject *)&SHA384type); PyModule_AddObject(m, "SHA384Type", (PyObject *)&SHA384type); diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index e54f7a9b1c2..37b312396f9 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -7100,7 +7100,7 @@ PyInit__socket(void) } #endif - Py_TYPE(&sock_type) = &PyType_Type; + Py_SET_TYPE(&sock_type, &PyType_Type); m = PyModule_Create(&socketmodule); if (m == NULL) return NULL; diff --git a/Modules/unicodedata.c b/Modules/unicodedata.c index e99d914b797..58b1bc2d0a1 100644 --- a/Modules/unicodedata.c +++ b/Modules/unicodedata.c @@ -1455,7 +1455,7 @@ PyInit_unicodedata(void) { PyObject *m, *v; - Py_TYPE(&UCD_Type) = &PyType_Type; + Py_SET_TYPE(&UCD_Type, &PyType_Type); m = PyModule_Create(&unicodedatamodule); if (!m) diff --git a/Objects/floatobject.c b/Objects/floatobject.c index 26e238cf05a..dfc5b196f18 100644 --- a/Objects/floatobject.c +++ b/Objects/floatobject.c @@ -221,7 +221,7 @@ float_dealloc(PyFloatObject *op) return; } numfree++; - Py_TYPE(op) = (struct _typeobject *)free_list; + Py_SET_TYPE(op, (PyTypeObject *)free_list); free_list = op; } else diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index da329b4fbac..0a593261c41 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -52,7 +52,7 @@ PyModuleDef_Init(struct PyModuleDef* def) if (def->m_base.m_index == 0) { max_module_number++; Py_SET_REFCNT(def, 1); - Py_TYPE(def) = &PyModuleDef_Type; + Py_SET_TYPE(def, &PyModuleDef_Type); def->m_base.m_index = max_module_number; } return (PyObject*)def; diff --git a/Objects/object.c b/Objects/object.c index 58065424881..503fb867802 100644 --- a/Objects/object.c +++ b/Objects/object.c @@ -144,7 +144,7 @@ PyObject_Init(PyObject *op, PyTypeObject *tp) return PyErr_NoMemory(); } - Py_TYPE(op) = tp; + Py_SET_TYPE(op, tp); if (PyType_GetFlags(tp) & Py_TPFLAGS_HEAPTYPE) { Py_INCREF(tp); } diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 5b8d5a228e5..e6a84b017aa 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -4097,9 +4097,10 @@ object_set_class(PyObject *self, PyObject *value, void *closure) } if (compatible_for_assignment(oldto, newto, "__class__")) { - if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) + if (newto->tp_flags & Py_TPFLAGS_HEAPTYPE) { Py_INCREF(newto); - Py_TYPE(self) = newto; + } + Py_SET_TYPE(self, newto); if (oldto->tp_flags & Py_TPFLAGS_HEAPTYPE) Py_DECREF(oldto); return 0; @@ -5334,8 +5335,9 @@ PyType_Ready(PyTypeObject *type) NULL when type is &PyBaseObject_Type, and we know its ob_type is not NULL (it's initialized to &PyType_Type). But coverity doesn't know that. */ - if (Py_TYPE(type) == NULL && base != NULL) - Py_TYPE(type) = Py_TYPE(base); + if (Py_TYPE(type) == NULL && base != NULL) { + Py_SET_TYPE(type, Py_TYPE(base)); + } /* Initialize tp_bases */ bases = type->tp_bases; diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c index d104b646f01..18c737e7e40 100644 --- a/Objects/weakrefobject.c +++ b/Objects/weakrefobject.c @@ -882,10 +882,12 @@ PyWeakref_NewProxy(PyObject *ob, PyObject *callback) if (result != NULL) { PyWeakReference *prev; - if (PyCallable_Check(ob)) - Py_TYPE(result) = &_PyWeakref_CallableProxyType; - else - Py_TYPE(result) = &_PyWeakref_ProxyType; + if (PyCallable_Check(ob)) { + Py_SET_TYPE(result, &_PyWeakref_CallableProxyType); + } + else { + Py_SET_TYPE(result, &_PyWeakref_ProxyType); + } get_basic_refs(*list, &ref, &proxy); if (callback == NULL) { if (proxy != NULL) {