mirror of https://github.com/python/cpython
type_call() now detect bugs in type new and init
* Call _Py_CheckFunctionResult() to check for bugs in type constructors (tp_new) * Add assertions to ensure an exception was raised if tp_init failed or that no exception was raised if tp_init succeed Refactor also the function to have less indentation.
This commit is contained in:
parent
31eb5fbe89
commit
99bb14bf0c
|
@ -906,25 +906,33 @@ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
obj = type->tp_new(type, args, kwds);
|
obj = type->tp_new(type, args, kwds);
|
||||||
if (obj != NULL) {
|
obj = _Py_CheckFunctionResult((PyObject*)type, obj, NULL);
|
||||||
/* Ugly exception: when the call was type(something),
|
if (obj == NULL)
|
||||||
don't call tp_init on the result. */
|
return NULL;
|
||||||
if (type == &PyType_Type &&
|
|
||||||
PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
|
/* Ugly exception: when the call was type(something),
|
||||||
(kwds == NULL ||
|
don't call tp_init on the result. */
|
||||||
(PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
|
if (type == &PyType_Type &&
|
||||||
return obj;
|
PyTuple_Check(args) && PyTuple_GET_SIZE(args) == 1 &&
|
||||||
/* If the returned object is not an instance of type,
|
(kwds == NULL ||
|
||||||
it won't be initialized. */
|
(PyDict_Check(kwds) && PyDict_Size(kwds) == 0)))
|
||||||
if (!PyType_IsSubtype(Py_TYPE(obj), type))
|
return obj;
|
||||||
return obj;
|
|
||||||
type = Py_TYPE(obj);
|
/* If the returned object is not an instance of type,
|
||||||
if (type->tp_init != NULL) {
|
it won't be initialized. */
|
||||||
int res = type->tp_init(obj, args, kwds);
|
if (!PyType_IsSubtype(Py_TYPE(obj), type))
|
||||||
if (res < 0) {
|
return obj;
|
||||||
Py_DECREF(obj);
|
|
||||||
obj = NULL;
|
type = Py_TYPE(obj);
|
||||||
}
|
if (type->tp_init != NULL) {
|
||||||
|
int res = type->tp_init(obj, args, kwds);
|
||||||
|
if (res < 0) {
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
Py_DECREF(obj);
|
||||||
|
obj = NULL;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(!PyErr_Occurred());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return obj;
|
return obj;
|
||||||
|
|
Loading…
Reference in New Issue