From 1eba8bae9223600677dfa3a4ce8b7e4d2b8fd00d Mon Sep 17 00:00:00 2001 From: Mark Shannon Date: Wed, 21 Aug 2024 12:44:56 +0100 Subject: GH-123185: Check for `NULL` after calling `_PyEvalFramePushAndInit` (GH-123194) --- Include/internal/pycore_uop_metadata.h | 2 +- Lib/test/test_class.py | 13 +++++++++++++ Python/bytecodes.c | 6 +++++- Python/executor_cases.c.h | 6 +++++- Python/generated_cases.c.h | 6 +++++- 5 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index 15c0ac1..e2cba4d 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -226,7 +226,7 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = { [_CALL_STR_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_TUPLE_1] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CHECK_AND_ALLOCATE_OBJECT] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, - [_CREATE_INIT_FRAME] = HAS_ARG_FLAG | HAS_ESCAPES_FLAG, + [_CREATE_INIT_FRAME] = HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_EXIT_INIT_CHECK] = HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG, [_CALL_BUILTIN_CLASS] = HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, [_CALL_BUILTIN_O] = HAS_ARG_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG, diff --git a/Lib/test/test_class.py b/Lib/test/test_class.py index d1f828b..f6ec213 100644 --- a/Lib/test/test_class.py +++ b/Lib/test/test_class.py @@ -787,6 +787,19 @@ class ClassTests(unittest.TestCase): Type(i) self.assertEqual(calls, 100) + def test_specialization_class_call_doesnt_crash(self): + # gh-123185 + + class Foo: + def __init__(self, arg): + pass + + for _ in range(8): + try: + Foo() + except: + pass + from _testinternalcapi import has_inline_values diff --git a/Python/bytecodes.c b/Python/bytecodes.c index ec0f6ab..3edd374 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -3584,8 +3584,12 @@ dummy_func( args[-1] = self; init_frame = _PyEvalFramePushAndInit( tstate, init_func, NULL, args-1, oparg+1, NULL, shim); - frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; SYNC_SP(); + if (init_frame == NULL) { + _PyEval_FrameClearAndPop(tstate, shim); + ERROR_NO_POP(); + } + frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; /* Account for pushing the extra frame. * We don't check recursion depth here, * as it will be checked after start_frame */ diff --git a/Python/executor_cases.c.h b/Python/executor_cases.c.h index 9226b7a..1db8e50 100644 --- a/Python/executor_cases.c.h +++ b/Python/executor_cases.c.h @@ -4152,9 +4152,13 @@ args[-1] = self; init_frame = _PyEvalFramePushAndInit( tstate, init_func, NULL, args-1, oparg+1, NULL, shim); - frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); + if (init_frame == NULL) { + _PyEval_FrameClearAndPop(tstate, shim); + JUMP_TO_ERROR(); + } + frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; /* Account for pushing the extra frame. * We don't check recursion depth here, * as it will be checked after start_frame */ diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h index 27971ce..f4a5d2a 100644 --- a/Python/generated_cases.c.h +++ b/Python/generated_cases.c.h @@ -1020,9 +1020,13 @@ args[-1] = self; init_frame = _PyEvalFramePushAndInit( tstate, init_func, NULL, args-1, oparg+1, NULL, shim); - frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; stack_pointer += -2 - oparg; assert(WITHIN_STACK_BOUNDS()); + if (init_frame == NULL) { + _PyEval_FrameClearAndPop(tstate, shim); + goto error; + } + frame->return_offset = 1 + INLINE_CACHE_ENTRIES_CALL; /* Account for pushing the extra frame. * We don't check recursion depth here, * as it will be checked after start_frame */ -- cgit v0.12