Uh oh!
There was an error while loading. Please reload this page.
gh-125038: Crash after genexpr.gi_frame.f_locals manipulations is fixed - #125178
Conversation
…is fixed Some iterator checks are added for _FOR_ITER, _FOR_ITER_TIER_TWO and INSTRUMENTED_FOR_ITER bytecode implementations. TypeError is raised in case of tp_iternext == NULL. Tests on generator modifying through gi_frame.f_locals are added, both to genexpr generators and function generators.
Uh oh!
There was an error while loading. Please reload this page.
…e-125038.ffSLCz.rst Co-authored-by: Kirill Podoprigora <kirill.bast9@mail.ru>
| if (iternext == NULL) { | ||
| _PyErr_Format(tstate, PyExc_TypeError, | ||
| "'for' requires an object with " | ||
| "__iter__ method, got %.100s", |
There was a problem hiding this comment.
This error is incorrect as it's looking for __next__, not __iter__. I think we can use the same error as builtins.next():
PyErr_Format(PyExc_TypeError, "'%.200s' object is not an iterator",
Py_TYPE(it)->tp_name);
markshannon
commented
Oct 9, 2024
I think this is wrong approach. Rather than modifying Currently, the bytecode compiler assumes that local variables in generator expressions cannot be modified in The bytecode for Compare that with the code for Note the additional I think adding the |
efimov-mikhail
commented
Oct 9, 2024
So, basically, we want to provide equal results for such code fragments:
Have I got your idea correct on high level? IMHO, this will change be convenient. |
markshannon
commented
Oct 9, 2024
Yes, I think those should provide the same results. |
markshannon
commented
Oct 9, 2024
We also want to avoid emitting In other words, this function: deff(s):
return (xforxins)currently generates the following bytecode: I think it should generate: This is a behavior change, but I think a correct one. If |
efimov-mikhail
commented
Oct 9, 2024
Agree.
Could you please give some additional information about this behavior change? |
JelleZijlstra
commented
Oct 9, 2024
Currently, this happens: >>> (x for x in1)
Traceback (most recent call last):
File "<python-input-0>", line 1, in <module>
(x for x in 1)
^
TypeError: 'int' object is not iterableWith Mark's proposed change, this error would be thrown only when the generator is iterated over. I think either behavior is fine and I agree with Mark that the proposed change makes for a more elegant implementation, but it is a change in core language behavior that I could see impacting some users (e.g., if you put a try-except around the construction of the genexp), so I wouldn't feel comfortable making that change in a bugfix release. @markshannon what do you think of applying this PR's approach in the 3.13 branch, and your idea on main only? |
efimov-mikhail
commented
Oct 9, 2024
Understood. Thx for the clarification.
It looks like a good idea for me, since crash through f_locals modification is already fixed. There will be no problem in backports in the case of two separate PRs? |
markshannon
commented
Oct 9, 2024
My proposed fix should have no performance impact (it does no extra work), so I'd definitely prefer that. If you think that is too intrusive for 3.13, we could leave the |
efimov-mikhail
commented
Oct 9, 2024
I like the idea of new CHECK_ITER bytecode. What do you think about this plan:
And what about Python 3.12 and below? |
markshannon
commented
Oct 10, 2024
That sounds like a good plan. If the fix is simple enough, then we can backport to 3.12. |
New tests are moved back to test_generators.py. Tests on generator creation via FunctionType from gi_code are added.
efimov-mikhail
commented
Oct 18, 2024
It seems like this solution will be best tradeoff. |
c5d5bf4 to
890b936Comparemarkshannon
commented
Oct 21, 2024
This might introduce a small slowdown in 3.13, but it isn't in the loop, so shouldn't be an issue. I'm not worried about that though, as we can remove the other |
markshannon
left a comment
There was a problem hiding this comment.
Looks good me once you've agreed on a better name for ModifyTest.
efimov-mikhail
commented
Oct 21, 2024
It's okay for me to change name from "ModifyTest" to something. |
JelleZijlstra
commented
Oct 21, 2024
Either of those names works for me. |
efimov-mikhail
commented
Oct 22, 2024
It seems we have agreed. Anything else, or it could be merged? |
Thanks @efimov-mikhail for the PR, and @JelleZijlstra for merging it 🌮🎉.. I'm working now to backport this PR to: 3.13. |
Sorry, @efimov-mikhail and @JelleZijlstra, I could not cleanly backport this to |
…ipulations (pythonGH-125178) (cherry picked from commit 079875e) Co-authored-by: Mikhail Efimov <efimov.mikhail@gmail.com>
GH-125846 is a backport of this pull request to the 3.13 branch. |
Some iterator checks are added for _FOR_ITER, _FOR_ITER_TIER_TWO and INSTRUMENTED_FOR_ITER bytecode implementations. TypeError is raised in case of tp_iternext == NULL. Tests on generator modifying through gi_frame.f_locals are added, both to genexpr generators and function generators.
I've added some test cases to emphasize current code behavior and save it explicitly in tests.
IMHO, there is still a room to improvement.
Previous PR becomes incorrect (#125051) after my typo in git commands.
I'm sorry about that.
@JelleZijlstra, Could you please review this again?
Moreover, label "needs backport to 3.13" should be added once again.