Skip to content

Commit

Permalink
pythonGH-106057: Handle recursion errors in inline class calls proper…
Browse files Browse the repository at this point in the history
  • Loading branch information
markshannon committed Jul 7, 2023
1 parent e1d45b8 commit 24fb627
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 91 deletions.
15 changes: 15 additions & 0 deletions Lib/test/test_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -740,6 +740,21 @@ class A(0, 1, 2, 3, 4, 5, 6, 7, **d): pass
class A(0, *range(1, 8), **d, foo='bar'): pass
self.assertEqual(A, (tuple(range(8)), {'foo': 'bar'}))

def testClassCallRecursionLimit(self):
class C:
def __init__(self):
self.c = C()

with self.assertRaises(RecursionError):
C()

def add_one_level():
#Each call to C() consumes 2 levels, so offset by 1.
C()

with self.assertRaises(RecursionError):
add_one_level()


if __name__ == '__main__':
unittest.main()
7 changes: 4 additions & 3 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -2985,9 +2985,6 @@ dummy_func(
goto error;
}
Py_DECREF(tp);
if (_Py_EnterRecursivePy(tstate)) {
goto exit_unwind;
}
_PyInterpreterFrame *shim = _PyFrame_PushTrampolineUnchecked(
tstate, (PyCodeObject *)&_Py_InitCleanup, 1, 0);
assert(_PyCode_CODE((PyCodeObject *)shim->f_executable)[1].op.code == EXIT_INIT_CHECK);
Expand All @@ -3011,6 +3008,10 @@ dummy_func(
shim->previous = frame;
frame = cframe.current_frame = init_frame;
CALL_STAT_INC(inlined_py_calls);
/* Account for pushing the extra frame.
* We don't check recursion depth here,
* as it will be checked after start_frame */
tstate->py_recursion_remaining--;
goto start_frame;
}

Expand Down
20 changes: 10 additions & 10 deletions Python/executor_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 24fb627

Please sign in to comment.