Skip to content

basicblock_addop Assertion #109627

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

Closed
15r10nk opened this issue Sep 20, 2023 · 5 comments · Fixed by #109630
Closed

basicblock_addop Assertion #109627

15r10nk opened this issue Sep 20, 2023 · 5 comments · Fixed by #109630
Labels
3.12 only security fixes 3.13 bugs and security fixes release-blocker type-bug An unexpected behavior, bug, or error

Comments

@15r10nk
Copy link
Contributor

15r10nk commented Sep 20, 2023

Bug report

Bug description:

I found the following error with the latest cpython 3.12 from git (4a0c118), which I build myself with --with-pydebug enabled.

source:

def get_namespace_uri():
    while element and something:
        try:
            return something
        except:
            pass

output (Python 3.12.0rc3+):

python3: Python/flowgraph.c:114: basicblock_addop: Assertion `0 <= oparg && oparg < (1 << 30)' failed.

CPython versions tested on:

3.12

Operating systems tested on:

Linux

Linked PRs

@JelleZijlstra
Copy link
Member

Confirmed on main, 3.11 is fine. cc @iritkatriel for flowgraph.c.

I'll try to bisect but not sure I'll have time to finish the bisect.

@AlexWaygood AlexWaygood added 3.12 only security fixes 3.13 bugs and security fixes labels Sep 20, 2023
@iritkatriel
Copy link
Member

I'm looking. I don't think bisecting will help - the jump targets labels are new so you'll probably get to the large PR that added them.

@iritkatriel
Copy link
Member

iritkatriel commented Sep 20, 2023

In order to ensure that function exits have a line number, the compiler duplicates small exit blocks which (1) do not have a line number in any instruction and (2) have more than one predecessor. Since these blocks are jump targets (at least one predecessor reaches this block via a jump or exception), they need to have labels assigned to them. This was missing, and is added in the attached PR.

This begs the question "how did this ever work?"

The assertion that fails here is in a piece of code that transforms a conditional backwards jump into a conditional forward jump followed by an unconditional backward jump (because all backward jumps are unconditional). It is this code that asserted the label. In general the labels are not that useful this late in the compiler's process, they are mostly used in the code generation phase, before we have the CFG with a direct pointer from a jump to its target block.

The typical case of a small basic block is the "return None" of a function, and it is not a target of a conditional backward branch - this is what made this edge case rare.

@iritkatriel
Copy link
Member

@15r10nk - Thank you for finding this and for the tiny repro.

@15r10nk
Copy link
Contributor Author

15r10nk commented Sep 21, 2023

@iritkatriel thank you for fixing this bug.
I would also like to mention that I automatically minimized the example with pysource-minimize. maybe you will find that useful too.

Yhg1s pushed a commit that referenced this issue Sep 22, 2023
…mp target labels (#109630) (#109632)

gh-109627: duplicated smalll exit blocks need to be assigned jump target labels (#109630)

(cherry picked from commit 9ccf054)
csm10495 pushed a commit to csm10495/cpython that referenced this issue Sep 28, 2023
Glyphack pushed a commit to Glyphack/cpython that referenced this issue Sep 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.12 only security fixes 3.13 bugs and security fixes release-blocker type-bug An unexpected behavior, bug, or error
Projects
Development

Successfully merging a pull request may close this issue.

4 participants