]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-145008: Maintain stack consistency in CALL_BOUND_METHOD_EXACT_ARGS (GH...
authorKen Jin <kenjin@python.org>
Mon, 2 Mar 2026 20:09:02 +0000 (04:09 +0800)
committerGitHub <noreply@github.com>
Mon, 2 Mar 2026 20:09:02 +0000 (04:09 +0800)
Include/internal/pycore_opcode_metadata.h
Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-19-23-12.gh-issue-145008.tHYQv6.rst [new file with mode: 0644]
Python/bytecodes.c
Python/generated_cases.c.h

index a3d31bcbc4ab549a6291b9c0f7e65b7989761791..610e3cc2f2024d4ab6d21e01fd13f56f8de09f32 100644 (file)
@@ -1221,7 +1221,7 @@ _PyOpcode_macro_expansion[256] = {
     [BUILD_STRING] = { .nuops = 1, .uops = { { _BUILD_STRING, 0, 0 } } },
     [BUILD_TUPLE] = { .nuops = 1, .uops = { { _BUILD_TUPLE, 0, 0 } } },
     [CALL_BOUND_METHOD_EXACT_ARGS] = { .nuops = 9, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _INIT_CALL_BOUND_METHOD_EXACT_ARGS, 0, 0 }, { _CHECK_FUNCTION_EXACT_ARGS, 2, 1 }, { _CHECK_STACK_SPACE, 0, 0 }, { _CHECK_RECURSION_REMAINING, 0, 0 }, { _INIT_CALL_PY_EXACT_ARGS, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } },
-    [CALL_BOUND_METHOD_GENERAL] = { .nuops = 7, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, 0, 0 }, { _CHECK_RECURSION_REMAINING, 0, 0 }, { _PY_FRAME_GENERAL, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } },
+    [CALL_BOUND_METHOD_GENERAL] = { .nuops = 7, .uops = { { _CHECK_PEP_523, 0, 0 }, { _CHECK_RECURSION_REMAINING, 0, 0 }, { _CHECK_METHOD_VERSION, 2, 1 }, { _EXPAND_METHOD, 0, 0 }, { _PY_FRAME_GENERAL, 0, 0 }, { _SAVE_RETURN_OFFSET, 7, 3 }, { _PUSH_FRAME, 0, 0 } } },
     [CALL_BUILTIN_CLASS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_CLASS, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
     [CALL_BUILTIN_FAST] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
     [CALL_BUILTIN_FAST_WITH_KEYWORDS] = { .nuops = 2, .uops = { { _CALL_BUILTIN_FAST_WITH_KEYWORDS, 0, 0 }, { _CHECK_PERIODIC, 0, 0 } } },
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-19-23-12.gh-issue-145008.tHYQv6.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-19-19-23-12.gh-issue-145008.tHYQv6.rst
new file mode 100644 (file)
index 0000000..d378d2a
--- /dev/null
@@ -0,0 +1 @@
+Fix a bug when calling certain methods at the recursion limit which manifested as a corruption of Python's operand stack. Patch by Ken Jin.
index 42cddac048f3f6092c689da61960af0dcd3e0679..24568489f2d25d5f539b48c2ed422846ab50bf2d 100644 (file)
@@ -3241,9 +3241,11 @@ dummy_func(
         macro(CALL_BOUND_METHOD_GENERAL) =
             unused/1 + // Skip over the counter
             _CHECK_PEP_523 +
+            // gh-145008: We must check recursion before expanding method,
+            // otherwise we may leave the stack in an inconsistent state in 3.13.
+            _CHECK_RECURSION_REMAINING +
             _CHECK_METHOD_VERSION +
             _EXPAND_METHOD +
-            _CHECK_RECURSION_REMAINING +
             _PY_FRAME_GENERAL +
             _SAVE_RETURN_OFFSET +
             _PUSH_FRAME;
index d21499b2f5724a6b3aa3bda021ca8d86f9cf4e2d..ad49becdfcaa67c72bb87b93d77aea8a153b8a51 100644 (file)
             {
                 DEOPT_IF(tstate->interp->eval_frame, CALL);
             }
+            // _CHECK_RECURSION_REMAINING
+            {
+                DEOPT_IF(tstate->py_recursion_remaining <= 1, CALL);
+            }
             // _CHECK_METHOD_VERSION
             null = stack_pointer[-1 - oparg];
             callable = stack_pointer[-2 - oparg];
                 Py_INCREF(method);
                 Py_DECREF(callable);
             }
-            // _CHECK_RECURSION_REMAINING
-            {
-                DEOPT_IF(tstate->py_recursion_remaining <= 1, CALL);
-            }
             // _PY_FRAME_GENERAL
             args = &stack_pointer[-oparg];
             self_or_null = self;