8000 [3.8] bpo-33930: Fix segfault with deep recursion when cleaning metho… · python/cpython@09d814b · GitHub
[go: up one dir, main page]

Skip to content 10000

Commit 09d814b

Browse files
ambvpablogsal
andauthored
[3.8] bpo-33930: Fix segfault with deep recursion when cleaning method objects (GH-27678) (GH-27721)
(cherry picked from commit bfc2d5a) Co-authored-by: Pablo Galindo Salgado <Pablogsal@gmail.com>
1 parent 7f88aea commit 09d814b

File tree

3 files changed

+22
-1
lines changed
< 10000 /div>

3 files changed

+22
-1
lines changed

Lib/test/test_exceptions.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -982,6 +982,21 @@ def g():
982982
self.assertIsInstance(v, RecursionError, type(v))
983983
self.assertIn("maximum recursion depth exceeded", str(v))
984984

985+
986+
@cpython_only
987+
def test_crashcan_recursion(self):
988+
# See bpo-33930
989+
990+
def foo():
991+
o = object()
992+
for x in range(1_000_000):
993+
# Create a big chain of method objects that will trigger
994+
# a deep chain of calls when they need to be destructed.
995+
o = o.__dir__
996+
997+
foo()
998+
support.gc_collect()
999+
9851000
@cpython_only
9861001
def test_recursion_normalizing_exception(self):
9871002
# Issue #22898.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix segmentation fault with deep recursion when cleaning method objects.
2+
Patch by Augusto Goulart and Pablo Galindo.

Objects/methodobject.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,10 @@ PyCFunction_GetFlags(PyObject *op)
125125
static void
126126
meth_dealloc(PyCFunctionObject *m)
127127
{
128-
_PyObject_GC_UNTRACK(m);
128+
// The Py_TRASHCAN mechanism requires that we be able to
129+
// call PyObject_GC_UnTrack twice on an object.
130+
PyObject_GC_UnTrack(m);
131+
Py_TRASHCAN_BEGIN(m, meth_dealloc);
129132
if (m->m_weakreflist != NULL) {
130133
PyObject_ClearWeakRefs((PyObject*) m);
131134
}
@@ -139,6 +142,7 @@ meth_dealloc(PyCFunctionObject *m)
139142
else {
140143
PyObject_GC_Del(m);
141144
}
145+
Py_TRASHCAN_END;
142146
}
143147

144148
static PyObject *

0 commit comments

Comments
 (0)
0