From 71977b8e544c0296b78ec631e91f12808afdf51f Mon Sep 17 00:00:00 2001 From: cocolato Date: Wed, 25 Feb 2026 22:57:17 +0800 Subject: [PATCH 1/2] fix trace crash --- Include/internal/pycore_opcode_metadata.h | 4 ++-- Include/internal/pycore_uop_metadata.h | 2 +- Lib/test/test_capi/test_opt.py | 22 ++++++++++++++++++++++ Python/bytecodes.c | 7 +++++-- Python/record_functions.c.h | 11 ++++++----- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/Include/internal/pycore_opcode_metadata.h b/Include/internal/pycore_opcode_metadata.h index fa8337bd08d470..126bc7d7102925 100644 --- a/Include/internal/pycore_opcode_metadata.h +++ b/Include/internal/pycore_opcode_metadata.h @@ -1179,7 +1179,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [FORMAT_SIMPLE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [FORMAT_WITH_SPEC] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [FOR_ITER] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ERROR_NO_POP_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, - [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [FOR_ITER_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [FOR_ITER_LIST] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ESCAPES_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_RANGE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, [FOR_ITER_TUPLE] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_EXIT_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG }, @@ -1283,7 +1283,7 @@ const struct opcode_metadata _PyOpcode_opcode_metadata[267] = { [RETURN_GENERATOR] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [RETURN_VALUE] = { true, INSTR_FMT_IX, HAS_ESCAPES_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, [SEND] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_JUMP_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_UNPREDICTABLE_JUMP_FLAG | HAS_NEEDS_GUARD_IP_FLAG }, - [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_ESCAPES_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, + [SEND_GEN] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_DEOPT_FLAG | HAS_SYNC_SP_FLAG | HAS_NEEDS_GUARD_IP_FLAG | HAS_RECORDS_VALUE_FLAG }, [SETUP_ANNOTATIONS] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [SET_ADD] = { true, INSTR_FMT_IB, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG }, [SET_FUNCTION_ATTRIBUTE] = { true, INSTR_FMT_IB, HAS_ARG_FLAG }, diff --git a/Include/internal/pycore_uop_metadata.h b/Include/internal/pycore_uop_metadata.h index be06738b54ca67..33a4d17d766eb2 100644 --- a/Include/internal/pycore_uop_metadata.h +++ b/Include/internal/pycore_uop_metadata.h @@ -379,7 +379,7 @@ const uint32_t _PyUop_Flags[MAX_UOP_ID+1] = { [_RECORD_TOS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_TOS_TYPE] = HAS_RECORDS_VALUE_FLAG, [_RECORD_NOS] = HAS_RECORDS_VALUE_FLAG, - [_RECORD_NOS_GEN_FUNC] = HAS_ESCAPES_FLAG | HAS_RECORDS_VALUE_FLAG, + [_RECORD_NOS_GEN_FUNC] = HAS_RECORDS_VALUE_FLAG, [_RECORD_4OS] = HAS_RECORDS_VALUE_FLAG, [_RECORD_CALLABLE] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, [_RECORD_BOUND_METHOD] = HAS_ARG_FLAG | HAS_RECORDS_VALUE_FLAG, diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index fe1b45608841a2..90e2ed20d1f6b3 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -4114,6 +4114,28 @@ def __init__(self, name): PYTHON_JIT_SIDE_EXIT_INITIAL_VALUE="1") self.assertEqual(result[0].rc, 0, result) + def test_for_iter_gen_cleared_frame_does_not_crash(self): + # See: https://github.com/python/cpython/issues/145197 + result = script_helper.run_python_until_end('-c', textwrap.dedent(""" + def g(): + yield 1 + yield 2 + + for _ in range(4002): + for _ in g(): + pass + + for i in range(4002): + it = g() + if (i & 7) == 0: + next(it) + it.close() + for _ in it: + pass + """), + PYTHON_JIT="1", PYTHON_JIT_STRESS="1") + self.assertEqual(result[0].rc, 0, result) + def global_identity(x): return x diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 36af61412b7417..41323c4f54d9ed 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -5730,8 +5730,11 @@ dummy_func( tier2 op(_RECORD_NOS_GEN_FUNC, (nos, tos -- nos, tos)) { PyObject *obj = PyStackRef_AsPyObjectBorrow(nos); if (PyGen_Check(obj)) { - PyObject *func = (PyObject *)_PyFrame_GetFunction(&((PyGenObject *)obj)->gi_iframe); - RECORD_VALUE(func); + PyGenObject *gen = (PyGenObject *)obj; + _PyStackRef func = gen->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + RECORD_VALUE(PyStackRef_AsPyObjectBorrow(func)); + } } } diff --git a/Python/record_functions.c.h b/Python/record_functions.c.h index c6709f9a9d6bec..64cafcb326e111 100644 --- a/Python/record_functions.c.h +++ b/Python/record_functions.c.h @@ -32,11 +32,12 @@ void _PyOpcode_RecordFunction_NOS_GEN_FUNC(_PyInterpreterFrame *frame, _PyStackR nos = stack_pointer[-2]; PyObject *obj = PyStackRef_AsPyObjectBorrow(nos); if (PyGen_Check(obj)) { - _PyFrame_SetStackPointer(frame, stack_pointer); - PyObject *func = (PyObject *)_PyFrame_GetFunction(&((PyGenObject *)obj)->gi_iframe); - stack_pointer = _PyFrame_GetStackPointer(frame); - *recorded_value = (PyObject *)func; - Py_INCREF(*recorded_value); + PyGenObject *gen = (PyGenObject *)obj; + _PyStackRef func = gen->gi_iframe.f_funcobj; + if (!PyStackRef_IsNull(func)) { + *recorded_value = (PyObject *)PyStackRef_AsPyObjectBorrow(func); + Py_INCREF(*recorded_value); + } } } From 3f66e679c4c7a3505a93696daa43066fe4818a8a Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 15:02:10 +0000 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst new file mode 100644 index 00000000000000..6d6afe5abfea9c --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-02-25-15-02-08.gh-issue-145197.G6hAUk.rst @@ -0,0 +1 @@ +Fix JIT trace crash when recording function from cleared generator frame.