PEP 667 + PEP 709 segfaults from accessing closure variables bound by any inlined comprehensions #128396
Labels
3.13
bugs and security fixes
3.14
new features, bugs and security fixes
interpreter-core
(Objects, Python, Grammar, and Parser dirs)
type-bug
An unexpected behavior, bug, or error
type-crash
A hard crash of the interpreter, possibly with a core dump
Bug report
Bug description:
The segfault described here is related to PEP-667 and PEP-709.
I think I experienced a couple of similar but not same segfaults, and this here is just one of a few of them. I might be wrong though.
I'd like to start working on fixing this in order to possibly find more unhappy paths.
Reproduction
Here are a bunch of reproductions:
@alexmojaki also found
This one shows the problem the best:
Traceback
Conclusions
There must be a statement that allows to create a closure for a variable, for instance
k
, in a scope ("target scope"). It's eitherk = [...]
ork: int
in the repros.There must be an inlined comprehension that binds
k
as target (e.g.k = 1; [x for x in [0] if locals()]
doesn't cause segfault).After binding the variable during the evaluation of the inlined comprehension, something must fetch the contents of the PEP 667 proxy of the target scope.
The target scope must be any optimized scope (not confirmed for generator expressions), since only those involve PEP 667
FrameLocalsProxy
. That's the reason why the crash doesn't happen at a module/class level:or on Python <3.13, before PEP 667 had been introduced.
The iterable traversed in the comprehension isn't special (the crash doesn't happen for certain objects, e.g.
[None]
1,(...,)
, but happens for others, e.g.[0]
,range(1)
). Not confirmed for every platform.Thanks @Eclips4 for hints to finding the best reproduction. Thanks @trag1c for reporting the problem after accidentally running into it in a real-life use case.
I'm delighted to accept any help or guidance (cc @JelleZijlstra @carljm), as I want to author the patch to fix this issue and learn something in the process. Thanks!
CPython versions tested on:
3.13, 3.14, CPython main branch
Operating systems tested on:
Linux
Footnotes
Const lists (from displays) are compiled into tuples under the hood before the loop begins, so
[None]
here is equivalent to(None,)
. ↩The text was updated successfully, but these errors were encountered: