GH-123185: Check for `NULL` after calling `_PyEvalFramePushAndInit` (GH-123194)

This commit is contained in:
Mark Shannon 2024-08-21 12:44:56 +01:00 committed by GitHub
parent 90c892efea
commit 1eba8bae92
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 29 additions and 4 deletions

View File

@ -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,

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */