]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-149243: Check for recursion limits in `CALL_ALLOC_AND_ENTER_INIT` (#149310)
authorsobolevn <mail@sobolevn.me>
Sun, 3 May 2026 10:26:05 +0000 (13:26 +0300)
committerGitHub <noreply@github.com>
Sun, 3 May 2026 10:26:05 +0000 (13:26 +0300)
Include/internal/pycore_opcode_metadata.h
Misc/NEWS.d/next/Core_and_Builtins/2026-05-03-10-24-50.gh-issue-149243.Zh1q9_.rst [new file with mode: 0644]
Modules/_testinternalcapi/test_cases.c.h
Python/bytecodes.c
Python/generated_cases.c.h

index 4f8b48db23d1efb3320b53e901fa72923bdc1766..0d7e367a5618b2876b7c755e40cad51d794acbcd 100644 (file)
@@ -1386,7 +1386,7 @@ _PyOpcode_macro_expansion[256] = {
     [BUILD_STRING] = { .nuops = 1, .uops = { { _BUILD_STRING, OPARG_SIMPLE, 0 } } },
     [BUILD_TEMPLATE] = { .nuops = 1, .uops = { { _BUILD_TEMPLATE, OPARG_SIMPLE, 0 } } },
     [BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, OPARG_SIMPLE, 0 } } },
-    [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_OBJECT, 2, 1 }, { _ALLOCATE_OBJECT, OPARG_SIMPLE, 3 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } },
+    [CALL_ALLOC_AND_ENTER_INIT] = { .nuops = 7, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_OBJECT, 2, 1 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _ALLOCATE_OBJECT, OPARG_SIMPLE, 3 }, { _CREATE_INIT_FRAME, OPARG_SIMPLE, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } },
     [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 11, .uops = { { _RECORD_BOUND_METHOD, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, OPARG_SIMPLE, 1 }, { _CHECK_FUNCTION_VERSION, 2, 1 }, { _CHECK_FUNCTION_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _CHECK_STACK_SPACE, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _INIT_CALL_PY_EXACT_ARGS, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } },
     [CALL_BOUND_METHOD_GENERAL] = { .nuops = 8, .uops = { { _RECORD_BOUND_METHOD, OPARG_SIMPLE, 0 }, { _CHECK_PEP_523, OPARG_SIMPLE, 1 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, OPARG_SIMPLE, 3 }, { _CHECK_RECURSION_REMAINING, OPARG_SIMPLE, 3 }, { _PY_FRAME_GENERAL, OPARG_SIMPLE, 3 }, { _SAVE_RETURN_OFFSET, OPARG_SAVE_RETURN_OFFSET, 3 }, { _PUSH_FRAME, OPARG_SIMPLE, 3 } } },
     [CALL_BUILTIN_CLASS] = { .nuops = 6, .uops = { { _RECORD_CALLABLE, OPARG_SIMPLE, 0 }, { _GUARD_CALLABLE_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _CALL_BUILTIN_CLASS, OPARG_SIMPLE, 3 }, { _POP_TOP_OPARG, OPARG_SIMPLE, 3 }, { _POP_TOP, OPARG_SIMPLE, 3 }, { _CHECK_PERIODIC_AT_END, OPARG_REPLACED, 3 } } },
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-03-10-24-50.gh-issue-149243.Zh1q9_.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-03-10-24-50.gh-issue-149243.Zh1q9_.rst
new file mode 100644 (file)
index 0000000..5c1956f
--- /dev/null
@@ -0,0 +1 @@
+Check for recursion limits in ``CALL_ALLOC_AND_ENTER_INIT`` opcode.
index 8897854078bd4540e3ed4b235ea5bd08ed94b4be..bd69211fd222062ae58ef02a0cc34e69bcaf0175 100644 (file)
                     JUMP_TO_PREDICTED(CALL);
                 }
             }
+            // _CHECK_RECURSION_REMAINING
+            {
+                if (tstate->py_recursion_remaining <= 1) {
+                    UPDATE_MISS_STATS(CALL);
+                    assert(_PyOpcode_Deopt[opcode] == (CALL));
+                    JUMP_TO_PREDICTED(CALL);
+                }
+            }
             // _ALLOCATE_OBJECT
             {
                 PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);
index 4239ba58bc390b4d58e56578662067a90aade372..963391e7598fb68fe162d477b0dcb55627d631fa 100644 (file)
@@ -4737,6 +4737,7 @@ dummy_func(
             unused/1 +
             _CHECK_PEP_523 +
             _CHECK_OBJECT +
+            _CHECK_RECURSION_REMAINING +
             _ALLOCATE_OBJECT +
             _CREATE_INIT_FRAME +
             _PUSH_FRAME;
index dccee0e4a3b110338b96a268bd245ab6212471cb..105375e41e360ba7c2bccd007a7c5b5744bdf243 100644 (file)
                     JUMP_TO_PREDICTED(CALL);
                 }
             }
+            // _CHECK_RECURSION_REMAINING
+            {
+                if (tstate->py_recursion_remaining <= 1) {
+                    UPDATE_MISS_STATS(CALL);
+                    assert(_PyOpcode_Deopt[opcode] == (CALL));
+                    JUMP_TO_PREDICTED(CALL);
+                }
+            }
             // _ALLOCATE_OBJECT
             {
                 PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable);