[Python-checkins] [3.8] bpo-33930: Fix segfault with deep recursion when cleaning method objects (GH-27678) (GH-27721)

ambv webhook-mailer at python.org
Wed Aug 11 11:35:46 EDT 2021


https://github.com/python/cpython/commit/09d814b3833c2c852f4f233297b4561028782d2a
commit: 09d814b3833c2c852f4f233297b4561028782d2a
branch: 3.8
author: Łukasz Langa <lukasz at langa.pl>
committer: ambv <lukasz at langa.pl>
date: 2021-08-11T17:35:38+02:00
summary:

[3.8] bpo-33930: Fix segfault with deep recursion when cleaning method objects (GH-27678) (GH-27721)

(cherry picked from commit bfc2d5a5c4550ab3a2fadeb9459b4bd948ff61a2)

Co-authored-by: Pablo Galindo Salgado <Pablogsal at gmail.com>

files:
A Misc/NEWS.d/next/Core and Builtins/2021-08-09-14-29-52.bpo-33930.--5LQ-.rst
M Lib/test/test_exceptions.py
M Objects/methodobject.c

diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py
index 457b46e01ce317..a29a1a7a523946 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -982,6 +982,21 @@ def g():
         self.assertIsInstance(v, RecursionError, type(v))
         self.assertIn("maximum recursion depth exceeded", str(v))
 
+
+    @cpython_only
+    def test_crashcan_recursion(self):
+        # See bpo-33930
+
+        def foo():
+            o = object()
+            for x in range(1_000_000):
+                # Create a big chain of method objects that will trigger
+                # a deep chain of calls when they need to be destructed.
+                o = o.__dir__
+
+        foo()
+        support.gc_collect()
+
     @cpython_only
     def test_recursion_normalizing_exception(self):
         # Issue #22898.
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-09-14-29-52.bpo-33930.--5LQ-.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-09-14-29-52.bpo-33930.--5LQ-.rst
new file mode 100644
index 00000000000000..827dd3f8b65131
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2021-08-09-14-29-52.bpo-33930.--5LQ-.rst	
@@ -0,0 +1,2 @@
+Fix segmentation fault with deep recursion when cleaning method objects.
+Patch by Augusto Goulart and Pablo Galindo.
diff --git a/Objects/methodobject.c b/Objects/methodobject.c
index 3604a55e5a1dc9..940de8c326f153 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -125,7 +125,10 @@ PyCFunction_GetFlags(PyObject *op)
 static void
 meth_dealloc(PyCFunctionObject *m)
 {
-    _PyObject_GC_UNTRACK(m);
+    // The Py_TRASHCAN mechanism requires that we be able to
+    // call PyObject_GC_UnTrack twice on an object.
+    PyObject_GC_UnTrack(m);
+    Py_TRASHCAN_BEGIN(m, meth_dealloc);
     if (m->m_weakreflist != NULL) {
         PyObject_ClearWeakRefs((PyObject*) m);
     }
@@ -139,6 +142,7 @@ meth_dealloc(PyCFunctionObject *m)
     else {
         PyObject_GC_Del(m);
     }
+    Py_TRASHCAN_END;
 }
 
 static PyObject *



More information about the Python-checkins mailing list