Skip to content

gh-130279: Fix missing exception handlers for jumps in loops - #159460

Open
LH-and-FPGA wants to merge 10 commits into
python:mainfrom
LH-and-FPGA:gh-130279-backward-jump-handler
Open

LH-and-FPGA wants to merge 10 commits into
python:mainfrom
LH-and-FPGA:gh-130279-backward-jump-handler

Conversation

@LH-and-FPGA

Copy link
Copy Markdown

When a loop body ends with an if whose false branch jumps back to the loop head, the backward jump ended up outside the exception table ranges of the enclosing try/with. An exception raised when that JUMP_BACKWARD checks the eval breaker (e.g. KeyboardInterrupt, or an async exception set via PyThreadState_SetAsyncExc) then skipped the except/finally blocks, and __exit__ was not called for with blocks.

def scan(items):
    try:
        for x in items:
            if x < 0:
                raise ValueError(x)
    except KeyboardInterrupt:
        return "handled"

Two places in Python/flowgraph.c created jump instructions without an exception handler after label_exception_targets() had already run:

  • jump_thread() replaced the original jump with a new one, dropping its i_except.
  • normalize_jumps_in_block() added NOT_TAKEN + JUMP for backward conditional jumps without copying the handler.

Both now copy the handler of the original jump.

@python-cla-bot

python-cla-bot Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

Comment thread Python/flowgraph.c Outdated
@@ -586,6 +586,13 @@ normalize_jumps_in_block(cfg_builder *g, basicblock *b) {
basicblock_addop(backwards_jump, NOT_TAKEN, 0, last->i_loc));
RETURN_IF_ERROR(
basicblock_add_jump(backwards_jump, JUMP, target, last->i_loc));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We could add an except arg to basicblock_addop and basicblock_add_jump (pass NULL if there is none).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks, I'll add an except on those places which replaces the post-hoc fixups.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

While doing this I noticed that the forward-branch NOT_TAKEN in normalize_jumps_in_block() also gets no handler, which leaves a gap in the exception table. It could matter when a sys.monitoring BRANCH_LEFT callback raises. Should I fix it here, or in a separate issue?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Fix it here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Sure

Comment thread Python/flowgraph.c Outdated
Comment on lines +587 to +590
/* The new instructions are covered by the same exception handler as
* the conditional jump, since the backward jump can raise when it
* checks the eval breaker.
*/

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think this comment is necessary. We copy i_loc and i_except, it makes sense.

@iritkatriel

Copy link
Copy Markdown
Member

Does this need to be backported?

@LH-and-FPGA

Copy link
Copy Markdown
Author

Does this need to be backported?

Do you mean fix this for 3.13 3.14 and 3.15?

@iritkatriel

Copy link
Copy Markdown
Member

Yes.

@LH-and-FPGA

Copy link
Copy Markdown
Author

Yes.

3.14 and 3.15 have the same code, so I think it should go to both. 3.13 and 3.12 has the backward jump issue as well, but it's security-only now. so how should I backport in general? Thanks

@iritkatriel iritkatriel added needs backport to 3.14 bugs and security fixes needs backport to 3.15 bugs and security fixes labels Oct 18, 2026
Comment thread Lib/test/test_compile.py Outdated
@LH-and-FPGA

LH-and-FPGA commented Oct 18, 2026 •

Copy link
Copy Markdown
Author

Does this need to be backported?

I found this https://devguide.python.org/getting-started/git-boot-camp/#backporting-merged-changes, so basically I don't need to do anything I think?

Comment thread Misc/NEWS.d/next/Core_and_Builtins/2026-10-15-12-36-09.gh-issue-130279.N9N-sw.rst Outdated
Comment thread Python/flowgraph.c Outdated
basicblock_add_jump(
bb, opcode, target->i_target, target->i_loc));
bb, opcode, target->i_target, target->i_loc,
inst->i_except));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why are we taking location from target but handler from inst?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

they should be the same in practice. jumps don't change the exception stack, and at this stage the NOPs left by POP_BLOCK haven't been removed yet, so threading never crosses a try boundary ( and I checked by compiling the stdlib with a debug check, and there were no mismatches). But the new jump stands in for target, so does that mean taking both from target is more consistent? Thanks.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Let's take it from target then, so it doesn't look strange.

I'm seeing some failures in test_dis on the builedbot.

@iritkatriel

Copy link
Copy Markdown
Member

Does this need to be backported?

I found this https://devguide.python.org/getting-started/git-boot-camp/#backporting-merged-changes, so basically I don't need to do anything I think?

I put the labels for back porting. If it goes smoothly you don't do anything. If there are conflicts you'll need to resolve them (create the back port manually off the 3.14/3.15 branches).

@iritkatriel

Copy link
Copy Markdown
Member

Is this your first PR? If so then add your name to the contributors file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review needs backport to 3.14 bugs and security fixes needs backport to 3.15 bugs and security fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants