summaryrefslogtreecommitdiffstats
path: root/Objects
diff options
context:
space:
mode:
authorDennis Sweeney <36520290+sweeneyde@users.noreply.github.com>2022-04-21 06:06:35 (GMT)
committerGitHub <noreply@github.com>2022-04-21 06:06:35 (GMT)
commitf2b4e458b3327130e46edb4efe8e1847de09efc5 (patch)
treedd53bed89cdbccf19083f11038516f20c6aa4036 /Objects
parent615b24c80b0bbbc7b70aa1e9c28f9c4463c8c1ed (diff)
downloadcpython-f2b4e458b3327130e46edb4efe8e1847de09efc5.zip
cpython-f2b4e458b3327130e46edb4efe8e1847de09efc5.tar.gz
cpython-f2b4e458b3327130e46edb4efe8e1847de09efc5.tar.bz2
gh-91636: Don't clear required fields of function objects (GH-91651)
Diffstat (limited to 'Objects')
-rw-r--r--Objects/funcobject.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/Objects/funcobject.c b/Objects/funcobject.c
index deacfd5..1e0cfb7 100644
--- a/Objects/funcobject.c
+++ b/Objects/funcobject.c
@@ -678,11 +678,8 @@ static int
func_clear(PyFunctionObject *op)
{
op->func_version = 0;
- Py_CLEAR(op->func_code);
Py_CLEAR(op->func_globals);
Py_CLEAR(op->func_builtins);
- Py_CLEAR(op->func_name);
- Py_CLEAR(op->func_qualname);
Py_CLEAR(op->func_module);
Py_CLEAR(op->func_defaults);
Py_CLEAR(op->func_kwdefaults);
@@ -690,6 +687,13 @@ func_clear(PyFunctionObject *op)
Py_CLEAR(op->func_dict);
Py_CLEAR(op->func_closure);
Py_CLEAR(op->func_annotations);
+ // Don't Py_CLEAR(op->func_code), since code is always required
+ // to be non-NULL. Similarly, name and qualname shouldn't be NULL.
+ // However, name and qualname could be str subclasses, so they
+ // could have reference cycles. The solution is to replace them
+ // with a genuinely immutable string.
+ Py_SETREF(op->func_name, Py_NewRef(&_Py_STR(empty)));
+ Py_SETREF(op->func_qualname, Py_NewRef(&_Py_STR(empty)));
return 0;
}
@@ -701,6 +705,10 @@ func_dealloc(PyFunctionObject *op)
PyObject_ClearWeakRefs((PyObject *) op);
}
(void)func_clear(op);
+ // These aren't cleared by func_clear().
+ Py_DECREF(op->func_code);
+ Py_DECREF(op->func_name);
+ Py_DECREF(op->func_qualname);
PyObject_GC_Del(op);
}