bpo-42412: Fix possible leaks and check arguments in PyType_FromModuleAndSpec() (GH-23410)
* There were leaks if Py_tp_bases is used more than once or if some call is failed before setting tp_bases. * There was a crash if the bases argument or the Py_tp_bases slot is not a tuple. * The documentation was not accurate.
This commit is contained in:
parent
01a202ab6b
commit
1db76394ea
|
@ -157,7 +157,8 @@ The following functions and structs are used to create
|
||||||
If *bases* is a tuple, the created heap type contains all types contained
|
If *bases* is a tuple, the created heap type contains all types contained
|
||||||
in it as base types.
|
in it as base types.
|
||||||
|
|
||||||
If *bases* is ``NULL``, the *Py_tp_base* slot is used instead.
|
If *bases* is ``NULL``, the *Py_tp_bases* slot is used instead.
|
||||||
|
If that also is ``NULL``, the *Py_tp_base* slot is used instead.
|
||||||
If that also is ``NULL``, the new type derives from :class:`object`.
|
If that also is ``NULL``, the new type derives from :class:`object`.
|
||||||
|
|
||||||
The *module* argument can be used to record the module in which the new
|
The *module* argument can be used to record the module in which the new
|
||||||
|
@ -253,7 +254,8 @@ The following functions and structs are used to create
|
||||||
* :c:member:`~PyBufferProcs.bf_getbuffer`
|
* :c:member:`~PyBufferProcs.bf_getbuffer`
|
||||||
* :c:member:`~PyBufferProcs.bf_releasebuffer`
|
* :c:member:`~PyBufferProcs.bf_releasebuffer`
|
||||||
|
|
||||||
Setting :c:data:`Py_tp_bases` may be problematic on some platforms.
|
Setting :c:data:`Py_tp_bases` or :c:data:`Py_tp_base` may be
|
||||||
|
problematic on some platforms.
|
||||||
To avoid issues, use the *bases* argument of
|
To avoid issues, use the *bases* argument of
|
||||||
:py:func:`PyType_FromSpecWithBases` instead.
|
:py:func:`PyType_FromSpecWithBases` instead.
|
||||||
|
|
||||||
|
|
|
@ -2977,26 +2977,40 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
||||||
base = slot->pfunc;
|
base = slot->pfunc;
|
||||||
else if (slot->slot == Py_tp_bases) {
|
else if (slot->slot == Py_tp_bases) {
|
||||||
bases = slot->pfunc;
|
bases = slot->pfunc;
|
||||||
Py_INCREF(bases);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!bases)
|
if (!bases) {
|
||||||
bases = PyTuple_Pack(1, base);
|
bases = PyTuple_Pack(1, base);
|
||||||
if (!bases)
|
if (!bases)
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else if (!PyTuple_Check(bases)) {
|
||||||
|
PyErr_SetString(PyExc_SystemError, "Py_tp_bases is not a tuple");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_INCREF(bases);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (!PyTuple_Check(bases)) {
|
||||||
|
PyErr_SetString(PyExc_SystemError, "bases is not a tuple");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
else {
|
||||||
Py_INCREF(bases);
|
Py_INCREF(bases);
|
||||||
|
}
|
||||||
|
|
||||||
/* Calculate best base, and check that all bases are type objects */
|
/* Calculate best base, and check that all bases are type objects */
|
||||||
base = best_base(bases);
|
base = best_base(bases);
|
||||||
if (base == NULL) {
|
if (base == NULL) {
|
||||||
|
Py_DECREF(bases);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if (!_PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
|
if (!_PyType_HasFeature(base, Py_TPFLAGS_BASETYPE)) {
|
||||||
PyErr_Format(PyExc_TypeError,
|
PyErr_Format(PyExc_TypeError,
|
||||||
"type '%.100s' is not an acceptable base type",
|
"type '%.100s' is not an acceptable base type",
|
||||||
base->tp_name);
|
base->tp_name);
|
||||||
|
Py_DECREF(bases);
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3008,7 +3022,6 @@ PyType_FromModuleAndSpec(PyObject *module, PyType_Spec *spec, PyObject *bases)
|
||||||
type->tp_as_buffer = &res->as_buffer;
|
type->tp_as_buffer = &res->as_buffer;
|
||||||
/* Set tp_base and tp_bases */
|
/* Set tp_base and tp_bases */
|
||||||
type->tp_bases = bases;
|
type->tp_bases = bases;
|
||||||
bases = NULL;
|
|
||||||
Py_INCREF(base);
|
Py_INCREF(base);
|
||||||
type->tp_base = base;
|
type->tp_base = base;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue