mirror of https://github.com/python/cpython
bpo-44263: Py_TPFLAGS_HAVE_GC requires tp_traverse (GH-26463)
The PyType_Ready() function now raises an error if a type is defined with the Py_TPFLAGS_HAVE_GC flag set but has no traverse function (PyTypeObject.tp_traverse).
This commit is contained in:
parent
fcda0f508e
commit
ee7637596d
|
@ -144,6 +144,11 @@ New Features
|
|||
Porting to Python 3.11
|
||||
----------------------
|
||||
|
||||
* The :c:func:`PyType_Ready` function now raises an error if a type is defined
|
||||
with the :const:`Py_TPFLAGS_HAVE_GC` flag set but has no traverse function
|
||||
(:c:member:`PyTypeObject.tp_traverse`).
|
||||
(Contributed by Victor Stinner in :issue:`44263`.)
|
||||
|
||||
Deprecated
|
||||
----------
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
The :c:func:`PyType_Ready` function now raises an error if a type is defined
|
||||
with the :const:`Py_TPFLAGS_HAVE_GC` flag set but has no traverse function
|
||||
(:c:member:`PyTypeObject.tp_traverse`).
|
||||
Patch by Victor Stinner.
|
|
@ -158,6 +158,12 @@ _PyType_CheckConsistency(PyTypeObject *type)
|
|||
CHECK(!(type->tp_flags & Py_TPFLAGS_READYING));
|
||||
CHECK(type->tp_dict != NULL);
|
||||
|
||||
if (type->tp_flags & Py_TPFLAGS_HAVE_GC) {
|
||||
// bpo-44263: tp_traverse is required if Py_TPFLAGS_HAVE_GC is set.
|
||||
// Note: tp_clear is optional.
|
||||
CHECK(type->tp_traverse != NULL);
|
||||
}
|
||||
|
||||
if (type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION) {
|
||||
CHECK(type->tp_new == NULL);
|
||||
CHECK(_PyDict_ContainsId(type->tp_dict, &PyId___new__) == 0);
|
||||
|
@ -3607,6 +3613,7 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
|||
}
|
||||
}
|
||||
|
||||
assert(_PyType_CheckConsistency(type));
|
||||
return (PyObject*)res;
|
||||
|
||||
fail:
|
||||
|
@ -5944,7 +5951,7 @@ static int add_tp_new_wrapper(PyTypeObject *type);
|
|||
#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
|
||||
|
||||
static int
|
||||
type_ready_checks(PyTypeObject *type)
|
||||
type_ready_pre_checks(PyTypeObject *type)
|
||||
{
|
||||
/* Consistency checks for PEP 590:
|
||||
* - Py_TPFLAGS_METHOD_DESCRIPTOR requires tp_descr_get
|
||||
|
@ -6305,10 +6312,28 @@ type_ready_set_new(PyTypeObject *type)
|
|||
}
|
||||
|
||||
|
||||
static int
|
||||
type_ready_post_checks(PyTypeObject *type)
|
||||
{
|
||||
// bpo-44263: tp_traverse is required if Py_TPFLAGS_HAVE_GC is set.
|
||||
// Note: tp_clear is optional.
|
||||
if (type->tp_flags & Py_TPFLAGS_HAVE_GC
|
||||
&& type->tp_traverse == NULL)
|
||||
{
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"type %s has the Py_TPFLAGS_HAVE_GC flag "
|
||||
"but has no traverse function",
|
||||
type->tp_name);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
type_ready(PyTypeObject *type)
|
||||
{
|
||||
if (type_ready_checks(type) < 0) {
|
||||
if (type_ready_pre_checks(type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -6346,6 +6371,9 @@ type_ready(PyTypeObject *type)
|
|||
if (type_ready_add_subclasses(type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (type_ready_post_checks(type) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue