Skip to content

Commit bda5a2b

Browse files
committed
Issue python#29358: Add postcondition checks on types
1 parent fc48908 commit bda5a2b

1 file changed

Lines changed: 24 additions & 3 deletions

File tree

Objects/typeobject.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,22 @@ skip_signature(const char *doc)
121121
return NULL;
122122
}
123123

124+
#ifdef Py_DEBUG
125+
static int
126+
_PyType_CheckConsistency(PyTypeObject *type)
127+
{
128+
if (!(type->tp_flags & Py_TPFLAGS_READY)) {
129+
/* don't check types before PyType_Ready() */
130+
return 1;
131+
}
132+
133+
assert(!(type->tp_flags & Py_TPFLAGS_READYING));
134+
assert(type->tp_mro != NULL && PyTuple_Check(type->tp_mro));
135+
assert(type->tp_dict != NULL);
136+
return 1;
137+
}
138+
#endif
139+
124140
static const char *
125141
_PyType_DocWithoutSignature(const char *name, const char *internal_doc)
126142
{
@@ -719,6 +735,7 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context)
719735
Py_DECREF(old_bases);
720736
Py_DECREF(old_base);
721737

738+
assert(_PyType_CheckConsistency(type));
722739
return res;
723740

724741
undo:
@@ -752,6 +769,7 @@ type_set_bases(PyTypeObject *type, PyObject *new_bases, void *context)
752769
Py_DECREF(old_base);
753770
}
754771

772+
assert(_PyType_CheckConsistency(type));
755773
return -1;
756774
}
757775

@@ -3034,6 +3052,7 @@ type_getattro(PyTypeObject *type, PyObject *name)
30343052
static int
30353053
type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
30363054
{
3055+
int res;
30373056
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
30383057
PyErr_Format(
30393058
PyExc_TypeError,
@@ -3043,7 +3062,9 @@ type_setattro(PyTypeObject *type, PyObject *name, PyObject *value)
30433062
}
30443063
if (_PyObject_GenericSetAttrWithDict((PyObject *)type, name, value, NULL) < 0)
30453064
return -1;
3046-
return update_slot(type, name);
3065+
res = update_slot(type, name);
3066+
assert(_PyType_CheckConsistency(type));
3067+
return res;
30473068
}
30483069

30493070
extern void
@@ -4851,7 +4872,7 @@ PyType_Ready(PyTypeObject *type)
48514872
Py_ssize_t i, n;
48524873

48534874
if (type->tp_flags & Py_TPFLAGS_READY) {
4854-
assert(type->tp_dict != NULL);
4875+
assert(_PyType_CheckConsistency(type));
48554876
return 0;
48564877
}
48574878
assert((type->tp_flags & Py_TPFLAGS_READYING) == 0);
@@ -5045,9 +5066,9 @@ PyType_Ready(PyTypeObject *type)
50455066
}
50465067

50475068
/* All done -- set the ready flag */
5048-
assert(type->tp_dict != NULL);
50495069
type->tp_flags =
50505070
(type->tp_flags & ~Py_TPFLAGS_READYING) | Py_TPFLAGS_READY;
5071+
assert(_PyType_CheckConsistency(type));
50515072
return 0;
50525073

50535074
error:

0 commit comments

Comments
 (0)