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 /Objects | |
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 'Objects')
-rw-r--r-- | Objects/typeobject.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/Objects/typeobject.c b/Objects/typeobject.c index 6540d4e..b6771d3 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -306,11 +306,14 @@ clear_tp_bases(PyTypeObject *self) { if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) { if (_Py_IsMainInterpreter(_PyInterpreterState_GET())) { - if (self->tp_bases != NULL - && PyTuple_GET_SIZE(self->tp_bases) > 0) - { - assert(_Py_IsImmortal(self->tp_bases)); - _Py_ClearImmortal(self->tp_bases); + if (self->tp_bases != NULL) { + if (PyTuple_GET_SIZE(self->tp_bases) == 0) { + Py_CLEAR(self->tp_bases); + } + else { + assert(_Py_IsImmortal(self->tp_bases)); + _Py_ClearImmortal(self->tp_bases); + } } } return; @@ -352,11 +355,14 @@ clear_tp_mro(PyTypeObject *self) { if (self->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) { if (_Py_IsMainInterpreter(_PyInterpreterState_GET())) { - if (self->tp_mro != NULL - && PyTuple_GET_SIZE(self->tp_mro) > 0) - { - assert(_Py_IsImmortal(self->tp_mro)); - _Py_ClearImmortal(self->tp_mro); + if (self->tp_mro != NULL) { + if (PyTuple_GET_SIZE(self->tp_mro) == 0) { + Py_CLEAR(self->tp_mro); + } + else { + assert(_Py_IsImmortal(self->tp_mro)); + _Py_ClearImmortal(self->tp_mro); + } } } return; @@ -6996,12 +7002,8 @@ type_ready_pre_checks(PyTypeObject *type) static int -type_ready_set_bases(PyTypeObject *type) +type_ready_set_base(PyTypeObject *type) { - if (lookup_tp_bases(type) != NULL) { - return 0; - } - /* Initialize tp_base (defaults to BaseObject unless that's us) */ PyTypeObject *base = type->tp_base; if (base == NULL && type != &PyBaseObject_Type) { @@ -7025,6 +7027,12 @@ type_ready_set_bases(PyTypeObject *type) } } + return 0; +} + +static int +type_ready_set_type(PyTypeObject *type) +{ /* Initialize ob_type if NULL. This means extensions that want to be compilable separately on Windows can call PyType_Ready() instead of initializing the ob_type field of their type objects. */ @@ -7032,11 +7040,25 @@ type_ready_set_bases(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. */ + PyTypeObject *base = type->tp_base; if (Py_IS_TYPE(type, NULL) && base != NULL) { Py_SET_TYPE(type, Py_TYPE(base)); } - /* Initialize tp_bases */ + return 0; +} + +static int +type_ready_set_bases(PyTypeObject *type) +{ + if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) { + if (!_Py_IsMainInterpreter(_PyInterpreterState_GET())) { + assert(lookup_tp_bases(type) != NULL); + return 0; + } + assert(lookup_tp_bases(type) == NULL); + } + PyObject *bases = lookup_tp_bases(type); if (bases == NULL) { PyTypeObject *base = type->tp_base; @@ -7446,6 +7468,12 @@ type_ready(PyTypeObject *type, int rerunbuiltin) if (type_ready_set_dict(type) < 0) { goto error; } + if (type_ready_set_base(type) < 0) { + goto error; + } + if (type_ready_set_type(type) < 0) { + goto error; + } if (type_ready_set_bases(type) < 0) { goto error; } |