From 3c452404ae178b742967589a0bb4a5ec768d76e0 Mon Sep 17 00:00:00 2001 From: INADA Naoki Date: Wed, 4 Jul 2018 11:15:50 +0900 Subject: [PATCH] bpo-33418: Add tp_clear for function object (GH-8058) Without tp_clear, GC can't break cyclic reference. It will cause memory leak when cyclic reference is created intentionally. --- .../2018-07-03-19-00-10.bpo-33418.cfGm3n.rst | 2 ++ Objects/funcobject.c | 34 ++++++++++++------- 2 files changed, 23 insertions(+), 13 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2018-07-03-19-00-10.bpo-33418.cfGm3n.rst diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-07-03-19-00-10.bpo-33418.cfGm3n.rst b/Misc/NEWS.d/next/Core and Builtins/2018-07-03-19-00-10.bpo-33418.cfGm3n.rst new file mode 100644 index 000000000000..8f136c6a35c1 --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2018-07-03-19-00-10.bpo-33418.cfGm3n.rst @@ -0,0 +1,2 @@ +Fix potential memory leak in function object when it creates reference +cycle. diff --git a/Objects/funcobject.c b/Objects/funcobject.c index 241685d5b7bb..c2f79c05dbb2 100644 --- a/Objects/funcobject.c +++ b/Objects/funcobject.c @@ -523,23 +523,31 @@ func_new_impl(PyTypeObject *type, PyCodeObject *code, PyObject *globals, return (PyObject *)newfunc; } +static int +func_clear(PyFunctionObject *op) +{ + Py_CLEAR(op->func_code); + Py_CLEAR(op->func_globals); + Py_CLEAR(op->func_module); + Py_CLEAR(op->func_name); + Py_CLEAR(op->func_defaults); + Py_CLEAR(op->func_kwdefaults); + Py_CLEAR(op->func_doc); + Py_CLEAR(op->func_dict); + Py_CLEAR(op->func_closure); + Py_CLEAR(op->func_annotations); + Py_CLEAR(op->func_qualname); + return 0; +} + static void func_dealloc(PyFunctionObject *op) { _PyObject_GC_UNTRACK(op); - if (op->func_weakreflist != NULL) + if (op->func_weakreflist != NULL) { PyObject_ClearWeakRefs((PyObject *) op); - Py_DECREF(op->func_code); - Py_DECREF(op->func_globals); - Py_XDECREF(op->func_module); - Py_DECREF(op->func_name); - Py_XDECREF(op->func_defaults); - Py_XDECREF(op->func_kwdefaults); - Py_XDECREF(op->func_doc); - Py_XDECREF(op->func_dict); - Py_XDECREF(op->func_closure); - Py_XDECREF(op->func_annotations); - Py_XDECREF(op->func_qualname); + } + (void)func_clear(op); PyObject_GC_Del(op); } @@ -612,7 +620,7 @@ PyTypeObject PyFunction_Type = { Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */ func_new__doc__, /* tp_doc */ (traverseproc)func_traverse, /* tp_traverse */ - 0, /* tp_clear */ + (inquiry)func_clear, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyFunctionObject, func_weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ -- 2.47.3