diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2023-06-01 22:28:31 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-01 22:28:31 (GMT) |
commit | 146939306adcff706ebddb047f7470d148125cdf (patch) | |
tree | 7ba1a0832da33fff49813d51dee801e54efd9fce /Modules | |
parent | 3698fda06eefb3c01e78c4c07f46fcdd0559e0f6 (diff) | |
download | cpython-146939306adcff706ebddb047f7470d148125cdf.zip cpython-146939306adcff706ebddb047f7470d148125cdf.tar.gz cpython-146939306adcff706ebddb047f7470d148125cdf.tar.bz2 |
gh-104614: Make Sure ob_type is Always Set Correctly by PyType_Ready() (gh-105122)
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.
Diffstat (limited to 'Modules')
-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 d7c89f4..38c2d1a 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -2640,6 +2640,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)) @@ -3395,6 +3439,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}, |