summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Include/internal/pycore_uop_metadata.h2
-rw-r--r--Lib/test/test_class.py13
-rw-r--r--Python/bytecodes.c6
-rw-r--r--Python/executor_cases.c.h6
-rw-r--r--Python/generated_cases.c.h6
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 */