Skip to content

bpo-38115: fix invalid lnotab after optimization #15970

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
wants to merge 6 commits into from

Conversation

Yhg1s
Copy link
Member

@Yhg1s Yhg1s commented Sep 11, 2019

Fix bpo-38115, a bug in the peephole optimizer that caused lnotab to have invalid bytecode offsets when the optimizer got rid of the last line(s) of a function. Also fix a bug where the optimizer bails out of optimization but leaves the lnotab modified. This is a very old bug, but before 3.8 the optimizer is more likely to successfully optimize away the last line of a function.

These don't change the bytecode that's generated, but they do change the code objects (the co_lnotab attribute), so though they theoretically affect Python 3.7 and earlier, we shouldn't backport this beyond 3.8. (Also, if you want to verify this manually, don't forget to touch the .py file or delete the .pyc file... not that I'm speaking of personal experience or anything.)

https://bugs.python.org/issue38115

…have

invalid bytecode offsets when the optimizer got rid of the last line(s) of a
function.

Also fix a bug where the optimizer bails out of optimization but leaves the
lnotab modified.
@Yhg1s
Copy link
Member Author

Yhg1s commented Sep 11, 2019

@markshannon might also be interested in this, I guess ;-P

@Yhg1s
Copy link
Member Author

Yhg1s commented Sep 11, 2019

Looks like the new assertion is getting triggered by code in test_scope, I'm digging into it.

…ix the

assert in the face of empty bytecode.
@Yhg1s
Copy link
Member Author

Yhg1s commented Sep 11, 2019

The assert didn't consider empty bytecode, that's now fixed.

@serhiy-storchaka serhiy-storchaka self-requested a review September 11, 2019 16:34
@Yhg1s
Copy link
Member Author

Yhg1s commented Sep 11, 2019

After some consideration, this is the wrong fix. See the test_pdb failure; replacing entries for past the end to the end makes consumers of lnotab think the last opcode of the function is part of the removed lines. Instead, what we should do is truncate lnotab. Unfortunately we can't do that, because PyCode_Optimize() is passed the lnotab as a PyBytes object, and can't resize it (because that may move it, which means the caller's object is invalid.)

Considering the peephole optimizer is likely to go away in 3.9, and this bug isn't that harmful (it doesn't confuse pdb or coverage), we should probably just document that the lnotab can contain invalid bytecode offsets and ignore it for now.

@pablogsal
Copy link
Member

Thanks @Yhg1s for helping me and for trying to solve this. I will update #14068 as we talked.

@Yhg1s Yhg1s closed this Sep 13, 2019
@Yhg1s Yhg1s deleted the lnotab branch September 13, 2019 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
awaiting core review type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants