-
-
Notifications
You must be signed in to change notification settings - Fork 31.7k
gh-131998: Fix NULL
dereference when using an unbound method descriptor in a specialized code path
#132000
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
gh-131998: Fix NULL
dereference when using an unbound method descriptor in a specialized code path
#132000
Conversation
ZeroIntensity
commented
Apr 2, 2025
•
edited by bedevere-app
bot
Loading
edited by bedevere-app
bot
- Issue: The interpreter crashes when specializing bound method calls on unbound objects #131998
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(not a full review)
Lib/test/test_types.py
Outdated
# GH-131998: The specialized instruction would get tricked into dereferencing | ||
# a bound "self" that didn't exist if subsequently called unbound. | ||
code = """if True: | ||
import glob |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this import?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, the optimizer is finicky and I can't get it to reliably reproduce without the import. I'll add a comment for clarity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reproduce the crash in a reliable way without the import glob
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it reliably reproduce in the test case? I think it only happens if you've already got some compiled bytecode to trigger the optimizer, which isn't the case in CI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can replace import glob
with just this code copied from Lib/types.py
(a dependency of glob
):
# CellType comes from types.py
def _cell_factory():
a = 1
def f():
nonlocal a
return f.__closure__[0]
CellType = type(_cell_factory())
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ok-ish with keeping import glob
, but add a comment explaining the purpose of this unused import.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it reliably reproduce in the test case? I think it only happens if you've already got some compiled bytecode to trigger the optimizer, which isn't the case in CI.
Sorry, I mean that I can reproduce the crash without import glob
when I run a script: ./python reproducer.py
. I confirm that for this test case, import glob
(or the code example that I proposed) is needed to trigger the bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import shouldn't be needed with the changes below.
Co-authored-by: sobolevn <[email protected]>
Co-authored-by: Victor Stinner <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to guard total_args
before reading self
.
This applies to CALL_METHOD_DESCRIPTOR_FAST
as well.
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase |
I have made the requested changes; please review again |
Thanks for making the requested changes! @markshannon: please review the changes made to this pull request. |
This PR had a merge conflict. Next 3.13/3.14 releases are tomorrow. |
Fixed the conflicts. Friendly ping @markshannon -- this is a blocker for 3.13.3. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove the import glob
by filling the stack with lists before the call.
Lib/test/test_types.py
Outdated
# GH-131998: The specialized instruction would get tricked into dereferencing | ||
# a bound "self" that didn't exist if subsequently called unbound. | ||
code = """if True: | ||
import glob |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This import shouldn't be needed with the changes below.
A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated. Once you have made the requested changes, please leave a comment on this pull request containing the phrase And if you don't make the requested changes, you will be poked with soft cushions! |
FTR, here's the reproducer on main without importing >>> def call(part):
... [] + ([] + [])
... part.pop()
...
>>> for _ in range(3):
... call(['a'])
...
>>> call(list)
Segmentation fault (core dumped) |
I'm not going to trigger the noisy bot again, but this should be good to go. |
Thanks @ZeroIntensity for the PR, and @Yhg1s for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13. |
Sorry, @ZeroIntensity and @Yhg1s, I could not cleanly backport this to
|
I'll deal with the backport. |
…method descriptor in a specialized code path (pythonGH-132000) (cherry picked from commit ac3c439) Co-authored-by: Peter Bierma <[email protected]> Co-authored-by: sobolevn <[email protected]> Co-authored-by: Victor Stinner <[email protected]> Co-authored-by: Mark Shannon <[email protected]>
GH-132262 is a backport of this pull request to the 3.13 branch. |
… descriptor in a specialized code path (GH-132000) (#132262) (cherry picked from commit ac3c439) Co-authored-by: Peter Bierma <[email protected]> Co-authored-by: sobolevn <[email protected]> Co-authored-by: Victor Stinner <[email protected]> Co-authored-by: Mark Shannon <[email protected]>
…descriptor in a specialized code path (python#132000) Co-authored-by: sobolevn <[email protected]> Co-authored-by: Victor Stinner <[email protected]> Co-authored-by: Mark Shannon <[email protected]>