[Python-checkins] bpo-33930: Fix segfault with deep recursion when cleaning method objects (GH-27678) (GH-27719)
vstinner
webhook-mailer at python.org
Wed Aug 11 04:32:49 EDT 2021
https://github.com/python/cpython/commit/d6d2d549972422ccc6fa335ebf9907e4b3d71817
commit: d6d2d549972422ccc6fa335ebf9907e4b3d71817
branch: 3.10
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: vstinner <vstinner at python.org>
date: 2021-08-11T10:32:44+02:00
summary:
bpo-33930: Fix segfault with deep recursion when cleaning method objects (GH-27678) (GH-27719)
(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 f50a246d849e1..10d48ebc076c3 100644
--- a/Lib/test/test_exceptions.py
+++ b/Lib/test/test_exceptions.py
@@ -1169,6 +1169,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 0000000000000..827dd3f8b6513
--- /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 7b430416c5a04..2df63cfdf6a81 100644
--- a/Objects/methodobject.c
+++ b/Objects/methodobject.c
@@ -160,7 +160,10 @@ PyCMethod_GetClass(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);
}
@@ -170,6 +173,7 @@ meth_dealloc(PyCFunctionObject *m)
Py_XDECREF(m->m_self);
Py_XDECREF(m->m_module);
PyObject_GC_Del(m);
+ Py_TRASHCAN_END;
}
static PyObject *
More information about the Python-checkins
mailing list