From 71b151d29388448c027c286246a50678a4852283 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 1 Aug 2025 18:51:40 +0100 Subject: [PATCH 1/5] gh-137288: Fix bug where boolean expressions are not associated with the correct exception handler --- Lib/test/test_compile.py | 15 +++++++++++++++ ...2025-08-01-18-54-31.gh-issue-137288.FhE7ku.rst | 2 ++ Python/flowgraph.c | 6 ++++++ 3 files changed, 23 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-08-01-18-54-31.gh-issue-137288.FhE7ku.rst diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 57e5f29b015637..8a66be9b331262 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -1723,6 +1723,21 @@ def test_compound(self): self.assertIs(res, v[3]) self.assertEqual([e.called for e in v], [1, 1, 0, 1, 0]) + def test_exception(self): + # See gh-137288 + class Foo: + def __bool__(self): + raise NotImplementedError() + + a = Foo() + b = Foo() + + with self.assertRaises(NotImplementedError): + bool(a) + + with self.assertRaises(NotImplementedError): + c = a or b + @requires_debug_ranges() class TestSourcePositions(unittest.TestCase): # Ensure that compiled code snippets have correct line and column numbers diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-08-01-18-54-31.gh-issue-137288.FhE7ku.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-01-18-54-31.gh-issue-137288.FhE7ku.rst new file mode 100644 index 00000000000000..37c143f18e76f7 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-08-01-18-54-31.gh-issue-137288.FhE7ku.rst @@ -0,0 +1,2 @@ +Fix bug where some bytecode instructions of a boolean expression are not +associated with the correct exception handler. diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 1cb6f03169e3b5..94e64d2c477323 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -3477,6 +3477,7 @@ convert_pseudo_conditional_jumps(cfg_builder *g) .i_oparg = 1, .i_loc = loc, .i_target = NULL, + .i_except = instr->i_except, }; RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, ©)); cfg_instr to_bool = { @@ -3484,6 +3485,7 @@ convert_pseudo_conditional_jumps(cfg_builder *g) .i_oparg = 0, .i_loc = loc, .i_target = NULL, + .i_except = instr->i_except, }; RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &to_bool)); } @@ -3726,6 +3728,7 @@ insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entrybl .i_oparg = 0, .i_loc = loc, .i_target = NULL, + .i_except = NULL, }; RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 0, &make_gen)); cfg_instr pop_top = { @@ -3733,6 +3736,7 @@ insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entrybl .i_oparg = 0, .i_loc = loc, .i_target = NULL, + .i_except = NULL, }; RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 1, &pop_top)); } @@ -3763,6 +3767,7 @@ insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entrybl .i_oparg = oldindex, .i_loc = NO_LOCATION, .i_target = NULL, + .i_except = NULL, }; if (basicblock_insert_instruction(entryblock, ncellsused, &make_cell) < 0) { PyMem_RawFree(sorted); @@ -3779,6 +3784,7 @@ insert_prefix_instructions(_PyCompile_CodeUnitMetadata *umd, basicblock *entrybl .i_oparg = nfreevars, .i_loc = NO_LOCATION, .i_target = NULL, + .i_except = NULL, }; RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 0, ©_frees)); } From ea4f664a4ef7ac144f74f57eca4422c086aeae26 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Fri, 1 Aug 2025 19:13:09 +0100 Subject: [PATCH 2/5] bump magic number --- Include/internal/pycore_magic_number.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 347d9762f26bff..a570ae684379a4 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -281,6 +281,7 @@ Known values: Python 3.15a1 3651 (Simplify LOAD_CONST) Python 3.15a1 3652 (Virtual iterators) Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST) + Python 3.15a1 3654 (Fix missing exception handlers in logical expression) Python 3.16 will start with 3700 @@ -294,7 +295,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3653 +#define PYC_MAGIC_NUMBER 3654 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ From d488c986b17779b5ff4e702d4b787aeb2f32316c Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 3 Aug 2025 14:04:55 +0100 Subject: [PATCH 3/5] fix crash --- Python/flowgraph.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Python/flowgraph.c b/Python/flowgraph.c index 94e64d2c477323..d82da15a43cac6 100644 --- a/Python/flowgraph.c +++ b/Python/flowgraph.c @@ -3472,12 +3472,13 @@ convert_pseudo_conditional_jumps(cfg_builder *g) instr->i_opcode = instr->i_opcode == JUMP_IF_FALSE ? POP_JUMP_IF_FALSE : POP_JUMP_IF_TRUE; location loc = instr->i_loc; + basicblock *except = instr->i_except; cfg_instr copy = { .i_opcode = COPY, .i_oparg = 1, .i_loc = loc, .i_target = NULL, - .i_except = instr->i_except, + .i_except = except, }; RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, ©)); cfg_instr to_bool = { @@ -3485,7 +3486,7 @@ convert_pseudo_conditional_jumps(cfg_builder *g) .i_oparg = 0, .i_loc = loc, .i_target = NULL, - .i_except = instr->i_except, + .i_except = except, }; RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &to_bool)); } From af2128c9316c44fee5fc99466fdf992b3d294b3b Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Sun, 3 Aug 2025 14:05:05 +0100 Subject: [PATCH 4/5] Revert "bump magic number" This reverts commit ea4f664a4ef7ac144f74f57eca4422c086aeae26. --- Include/internal/pycore_magic_number.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index a570ae684379a4..347d9762f26bff 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -281,7 +281,6 @@ Known values: Python 3.15a1 3651 (Simplify LOAD_CONST) Python 3.15a1 3652 (Virtual iterators) Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST) - Python 3.15a1 3654 (Fix missing exception handlers in logical expression) Python 3.16 will start with 3700 @@ -295,7 +294,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3654 +#define PYC_MAGIC_NUMBER 3653 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \ From 69708fe57913632bbee440a4cbbc795609d2e558 Mon Sep 17 00:00:00 2001 From: Irit Katriel Date: Tue, 5 Aug 2025 18:53:46 +0100 Subject: [PATCH 5/5] Reapply "bump magic number" This reverts commit af2128c9316c44fee5fc99466fdf992b3d294b3b. --- Include/internal/pycore_magic_number.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Include/internal/pycore_magic_number.h b/Include/internal/pycore_magic_number.h index 347d9762f26bff..a570ae684379a4 100644 --- a/Include/internal/pycore_magic_number.h +++ b/Include/internal/pycore_magic_number.h @@ -281,6 +281,7 @@ Known values: Python 3.15a1 3651 (Simplify LOAD_CONST) Python 3.15a1 3652 (Virtual iterators) Python 3.15a1 3653 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST) + Python 3.15a1 3654 (Fix missing exception handlers in logical expression) Python 3.16 will start with 3700 @@ -294,7 +295,7 @@ PC/launcher.c must also be updated. */ -#define PYC_MAGIC_NUMBER 3653 +#define PYC_MAGIC_NUMBER 3654 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes (little-endian) and then appending b'\r\n'. */ #define PYC_MAGIC_NUMBER_TOKEN \