]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-33418: Add tp_clear for function object (GH-8058)
authorINADA Naoki <methane@users.noreply.github.com>
Wed, 4 Jul 2018 02:15:50 +0000 (11:15 +0900)
committerGitHub <noreply@github.com>
Wed, 4 Jul 2018 02:15:50 +0000 (11:15 +0900)
Without tp_clear, GC can't break cyclic reference.
It will cause memory leak when cyclic reference is
created intentionally.

Misc/NEWS.d/next/Core and Builtins/2018-07-03-19-00-10.bpo-33418.cfGm3n.rst [new file with mode: 0644]
Objects/funcobject.c

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 (file)
index 0000000..8f136c6
--- /dev/null
@@ -0,0 +1,2 @@
+Fix potential memory leak in function object when it creates reference
+cycle.
index 241685d5b7bbf7784307ec17a45f468cd80f3fd3..c2f79c05dbb21b3ca7808abd2a266b4dea515ffb 100644 (file)
@@ -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 */