Skip to content

[3.14] gh-137288: Fix bug where boolean expressions are not associated with the correct exception handler (GH-137310). #137427

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Include/internal/pycore_magic_number.h
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ Known values:
Python 3.14a7 3623 (Add BUILD_INTERPOLATION & BUILD_TEMPLATE opcodes)
Python 3.14b1 3624 (Don't optimize LOAD_FAST when local is killed by DELETE_FAST)
Python 3.14b3 3625 (Fix handling of opcodes that may leave operands on the stack when optimizing LOAD_FAST)
Python 3.14b5 3626 (Fix missing exception handlers in logical expression)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should say 3.14rc2

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I opened #137665 to also add the missing 3.14 numbers to main and then we can backport.

Python 3.15 will start with 3650
Expand All @@ -290,7 +291,7 @@ PC/launcher.c must also be updated.
*/

#define PYC_MAGIC_NUMBER 3625
#define PYC_MAGIC_NUMBER 3626
/* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
(little-endian) and then appending b'\r\n'. */
#define PYC_MAGIC_NUMBER_TOKEN \
Expand Down
15 changes: 15 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_importlib/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ def test_magic_number(self):
# stakeholders such as OS package maintainers must be notified
# in advance. Such exceptional releases will then require an
# adjustment to this test case.
EXPECTED_MAGIC_NUMBER = 3625
EXPECTED_MAGIC_NUMBER = 3626
actual = int.from_bytes(importlib.util.MAGIC_NUMBER[:2], 'little')

msg = (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix bug where some bytecode instructions of a boolean expression are not
associated with the correct exception handler.
7 changes: 7 additions & 0 deletions Python/flowgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -3463,18 +3463,21 @@ 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 = except,
};
RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &copy));
cfg_instr to_bool = {
.i_opcode = TO_BOOL,
.i_oparg = 0,
.i_loc = loc,
.i_target = NULL,
.i_except = except,
};
RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &to_bool));
}
Expand Down Expand Up @@ -3717,13 +3720,15 @@ 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 = {
.i_opcode = POP_TOP,
.i_oparg = 0,
.i_loc = loc,
.i_target = NULL,
.i_except = NULL,
};
RETURN_IF_ERROR(basicblock_insert_instruction(entryblock, 1, &pop_top));
}
Expand Down Expand Up @@ -3754,6 +3759,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);
Expand All @@ -3770,6 +3776,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, &copy_frees));
}
Expand Down
Loading