diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2023-06-01 23:06:38 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-01 23:06:38 (GMT) |
commit | d57ee813ebd496a3fd8118d7dc057d54c4af847e (patch) | |
tree | 0ca49a125b77d250c937925e7405f72fc1cad978 /Modules/_testcapimodule.c | |
parent | d2be5c73ed520fb9d82a395f001eb9001711ed8f (diff) | |
download | cpython-d57ee813ebd496a3fd8118d7dc057d54c4af847e.zip cpython-d57ee813ebd496a3fd8118d7dc057d54c4af847e.tar.gz cpython-d57ee813ebd496a3fd8118d7dc057d54c4af847e.tar.bz2 |
[3.12] gh-104614: Make Sure ob_type is Always Set Correctly by PyType_Ready() (gh-105122) (gh-105211)
When I added the relevant condition to type_ready_set_bases() in gh-103912, I had missed that the function also sets tp_base and ob_type (if necessary). That led to problems for third-party static types.
We fix that here, by making those extra operations distinct and by adjusting the condition to be more specific.
(cherry picked from commit 1469393)
Co-authored-by: Eric Snow ericsnowcurrently@gmail.com
Diffstat (limited to 'Modules/_testcapimodule.c')
-rw-r--r-- | Modules/_testcapimodule.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 66c1cba..3caaca3 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2627,6 +2627,50 @@ type_get_tp_mro(PyObject *self, PyObject *type) } +/* We only use 2 in test_capi/test_misc.py. */ +#define NUM_BASIC_STATIC_TYPES 2 +static PyTypeObject BasicStaticTypes[NUM_BASIC_STATIC_TYPES] = { +#define INIT_BASIC_STATIC_TYPE \ + { \ + PyVarObject_HEAD_INIT(NULL, 0) \ + .tp_name = "BasicStaticType", \ + .tp_basicsize = sizeof(PyObject), \ + } + INIT_BASIC_STATIC_TYPE, + INIT_BASIC_STATIC_TYPE, +#undef INIT_BASIC_STATIC_TYPE +}; +static int num_basic_static_types_used = 0; + +static PyObject * +get_basic_static_type(PyObject *self, PyObject *args) +{ + PyObject *base = NULL; + if (!PyArg_ParseTuple(args, "|O", &base)) { + return NULL; + } + assert(base == NULL || PyType_Check(base)); + + if(num_basic_static_types_used >= NUM_BASIC_STATIC_TYPES) { + PyErr_SetString(PyExc_RuntimeError, "no more available basic static types"); + return NULL; + } + PyTypeObject *cls = &BasicStaticTypes[num_basic_static_types_used++]; + + if (base != NULL) { + cls->tp_base = (PyTypeObject *)Py_NewRef(base); + cls->tp_bases = Py_BuildValue("(O)", base); + if (cls->tp_bases == NULL) { + return NULL; + } + } + if (PyType_Ready(cls) < 0) { + return NULL; + } + return (PyObject *)cls; +} + + // Test PyThreadState C API static PyObject * test_tstate_capi(PyObject *self, PyObject *Py_UNUSED(args)) @@ -3384,6 +3428,7 @@ static PyMethodDef TestMethods[] = { {"type_assign_version", type_assign_version, METH_O, PyDoc_STR("PyUnstable_Type_AssignVersionTag")}, {"type_get_tp_bases", type_get_tp_bases, METH_O}, {"type_get_tp_mro", type_get_tp_mro, METH_O}, + {"get_basic_static_type", get_basic_static_type, METH_VARARGS, NULL}, {"test_tstate_capi", test_tstate_capi, METH_NOARGS, NULL}, {"frame_getlocals", frame_getlocals, METH_O, NULL}, {"frame_getglobals", frame_getglobals, METH_O, NULL}, |