bpo-33930: Fix segfault with deep recursion when cleaning method obje… · python/cpython@d6d2d54

File tree

3 files changed

lines changed

  • Misc/NEWS.d/next/Core and Builtins

3 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -1169,6 +1169,21 @@ def g():

11691169

self.assertIsInstance(v, RecursionError, type(v))

11701170

self.assertIn("maximum recursion depth exceeded", str(v))

11711171
1172+
1173+

@cpython_only

1174+

def test_crashcan_recursion(self):

1175+

# See bpo-33930

1176+
1177+

def foo():

1178+

o = object()

1179+

for x in range(1_000_000):

1180+

# Create a big chain of method objects that will trigger

1181+

# a deep chain of calls when they need to be destructed.

1182+

o = o.__dir__

1183+
1184+

foo()

1185+

support.gc_collect()

1186+
11721187

@cpython_only

11731188

def test_recursion_normalizing_exception(self):

11741189

# Issue #22898.

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.

Original file line numberDiff line numberDiff line change

@@ -160,7 +160,10 @@ PyCMethod_GetClass(PyObject *op)

160160

static void

161161

meth_dealloc(PyCFunctionObject *m)

162162

{

163-

_PyObject_GC_UNTRACK(m);

163+

// The Py_TRASHCAN mechanism requires that we be able to

164+

// call PyObject_GC_UnTrack twice on an object.

165+

PyObject_GC_UnTrack(m);

166+

Py_TRASHCAN_BEGIN(m, meth_dealloc);

164167

if (m->m_weakreflist != NULL) {

165168

PyObject_ClearWeakRefs((PyObject*) m);

166169

}

@@ -170,6 +173,7 @@ meth_dealloc(PyCFunctionObject *m)

170173

Py_XDECREF(m->m_self);

171174

Py_XDECREF(m->m_module);

172175

PyObject_GC_Del(m);

176+

Py_TRASHCAN_END;

173177

}

174178
175179

static PyObject *