bpo-42143: Ensure PyFunction_NewWithQualName() can't fail after creating the func object (GH-22953)

func_dealloc() does not handle partially-created objects. Best not to give it any.
This commit is contained in:
Yonatan Goldschmidt 2020-10-29 11:58:52 +02:00 committed by GitHub
parent df59273c7a
commit 350526105f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 19 additions and 14 deletions

View File

@ -0,0 +1,2 @@
Fix handling of errors during creation of ``PyFunctionObject``, which resulted
in operations on uninitialized memory. Patch by Yonatan Goldschmidt.

View File

@ -19,9 +19,23 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
return NULL;
}
op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
if (op == NULL)
/* __module__: If module name is in globals, use it.
Otherwise, use None. */
module = PyDict_GetItemWithError(globals, __name__);
if (module) {
Py_INCREF(module);
}
else if (PyErr_Occurred()) {
return NULL;
}
op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
if (op == NULL) {
Py_XDECREF(module);
return NULL;
}
/* Note: No failures from this point on, since func_dealloc() does not
expect a partially-created object. */
op->func_weakreflist = NULL;
Py_INCREF(code);
@ -34,6 +48,7 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
op->func_kwdefaults = NULL; /* No keyword only defaults */
op->func_closure = NULL;
op->vectorcall = _PyFunction_Vectorcall;
op->func_module = module;
consts = ((PyCodeObject *)code)->co_consts;
if (PyTuple_Size(consts) >= 1) {
@ -47,20 +62,8 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
op->func_doc = doc;
op->func_dict = NULL;
op->func_module = NULL;
op->func_annotations = NULL;
/* __module__: If module name is in globals, use it.
Otherwise, use None. */
module = PyDict_GetItemWithError(globals, __name__);
if (module) {
Py_INCREF(module);
op->func_module = module;
}
else if (PyErr_Occurred()) {
Py_DECREF(op);
return NULL;
}
if (qualname)
op->func_qualname = qualname;
else