summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-06-01 23:06:38 (GMT)
committerGitHub <noreply@github.com>2023-06-01 23:06:38 (GMT)
commitd57ee813ebd496a3fd8118d7dc057d54c4af847e (patch)
tree0ca49a125b77d250c937925e7405f72fc1cad978 /Objects
parentd2be5c73ed520fb9d82a395f001eb9001711ed8f (diff)
downloadcpython-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.c60
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;
}