gh-137288: Fix bug where boolean expressions are not associated with the correct exception handler (#137310)

This commit is contained in:
Irit Katriel 2025-08-05 19:25:57 +01:00 committed by GitHub
parent 525784aa65
commit 1f2026b8a2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 26 additions and 1 deletions

View file

@ -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 \

View file

@ -1723,6 +1723,21 @@ class TestBooleanExpression(unittest.TestCase):
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

View file

@ -0,0 +1,2 @@
Fix bug where some bytecode instructions of a boolean expression are not
associated with the correct exception handler.

View file

@ -3472,11 +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 = except,
};
RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &copy));
cfg_instr to_bool = {
@ -3484,6 +3486,7 @@ convert_pseudo_conditional_jumps(cfg_builder *g)
.i_oparg = 0,
.i_loc = loc,
.i_target = NULL,
.i_except = except,
};
RETURN_IF_ERROR(basicblock_insert_instruction(b, i++, &to_bool));
}
@ -3726,6 +3729,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 +3737,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 +3768,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 +3785,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));
}