Skip to content

Commit 9ede1b0

Browse files
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. (cherry picked from commit 3505261) Co-authored-by: Yonatan Goldschmidt <[email protected]>
1 parent b1ce044 commit 9ede1b0

File tree

2 files changed

+18
-13
lines changed

2 files changed

+18
-13
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix handling of errors during creation of ``PyFunctionObject``, which resulted
2+
in operations on uninitialized memory. Patch by Yonatan Goldschmidt.

Objects/funcobject.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,23 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
2222
return NULL;
2323
}
2424

25+
/* __module__: If module name is in globals, use it.
26+
Otherwise, use None. */
27+
module = PyDict_GetItemWithError(globals, __name__);
28+
if (module) {
29+
Py_INCREF(module);
30+
}
31+
else if (PyErr_Occurred()) {
32+
return NULL;
33+
}
34+
2535
op = PyObject_GC_New(PyFunctionObject, &PyFunction_Type);
26-
if (op == NULL)
36+
if (op == NULL) {
37+
Py_XDECREF(module);
2738
return NULL;
39+
}
40+
/* Note: No failures from this point on, since func_dealloc() does not
41+
expect a partially-created object. */
2842

2943
op->func_weakreflist = NULL;
3044
Py_INCREF(code);
@@ -37,6 +51,7 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
3751
op->func_kwdefaults = NULL; /* No keyword only defaults */
3852
op->func_closure = NULL;
3953
op->vectorcall = _PyFunction_Vectorcall;
54+
op->func_module = module;
4055

4156
consts = ((PyCodeObject *)code)->co_consts;
4257
if (PyTuple_Size(consts) >= 1) {
@@ -50,20 +65,8 @@ PyFunction_NewWithQualName(PyObject *code, PyObject *globals, PyObject *qualname
5065
op->func_doc = doc;
5166

5267
op->func_dict = NULL;
53-
op->func_module = NULL;
5468
op->func_annotations = NULL;
5569

56-
/* __module__: If module name is in globals, use it.
57-
Otherwise, use None. */
58-
module = PyDict_GetItemWithError(globals, __name__);
59-
if (module) {
60-
Py_INCREF(module);
61-
op->func_module = module;
62-
}
63-
else if (PyErr_Occurred()) {
64-
Py_DECREF(op);
65-
return NULL;
66-
}
6770
if (qualname)
6871
op->func_qualname = qualname;
6972
else

0 commit comments

Comments
 (0)