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
|
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
|
Deprecated
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
@ -180,4 +185,4 @@ Removed
|
||||||
parameter of functions :func:`~gettext.translation` and
|
parameter of functions :func:`~gettext.translation` and
|
||||||
:func:`~gettext.install` are also removed, since they are only used for
|
:func:`~gettext.install` are also removed, since they are only used for
|
||||||
the ``l*gettext()`` functions.
|
the ``l*gettext()`` functions.
|
||||||
(Contributed by Dong-hee Na and Serhiy Storchaka in :issue:`44235`.)
|
(Contributed by Dong-hee Na and Serhiy Storchaka in :issue:`44235`.)
|
||||||
|
|
|
@ -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_flags & Py_TPFLAGS_READYING));
|
||||||
CHECK(type->tp_dict != NULL);
|
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) {
|
if (type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION) {
|
||||||
CHECK(type->tp_new == NULL);
|
CHECK(type->tp_new == NULL);
|
||||||
CHECK(_PyDict_ContainsId(type->tp_dict, &PyId___new__) == 0);
|
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;
|
return (PyObject*)res;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
@ -5944,7 +5951,7 @@ static int add_tp_new_wrapper(PyTypeObject *type);
|
||||||
#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
|
#define COLLECTION_FLAGS (Py_TPFLAGS_SEQUENCE | Py_TPFLAGS_MAPPING)
|
||||||
|
|
||||||
static int
|
static int
|
||||||
type_ready_checks(PyTypeObject *type)
|
type_ready_pre_checks(PyTypeObject *type)
|
||||||
{
|
{
|
||||||
/* Consistency checks for PEP 590:
|
/* Consistency checks for PEP 590:
|
||||||
* - Py_TPFLAGS_METHOD_DESCRIPTOR requires tp_descr_get
|
* - 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
|
static int
|
||||||
type_ready(PyTypeObject *type)
|
type_ready(PyTypeObject *type)
|
||||||
{
|
{
|
||||||
if (type_ready_checks(type) < 0) {
|
if (type_ready_pre_checks(type) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6346,6 +6371,9 @@ type_ready(PyTypeObject *type)
|
||||||
if (type_ready_add_subclasses(type) < 0) {
|
if (type_ready_add_subclasses(type) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (type_ready_post_checks(type) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue