diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-10-27-21-34-05.bpo-42143.N6KXUO.rst b/Misc/NEWS.d/next/Core and Builtins/2020-10-27-21-34-05.bpo-42143.N6KXUO.rst new file mode 100644 index 00000000000000..2b16e69da73b5f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-10-27-21-34-05.bpo-42143.N6KXUO.rst @@ -0,0 +1,2 @@ +Fix handling of errors during creation of ``PyFunctionObject``, which resulted +in operations on uninitialized memory. Patch by Yonatan Goldschmidt. diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 09a188664e8611..9b4302a13c10f8 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -19,9 +19,23 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname return 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) + 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