-
-
Notifications
You must be signed in to change notification settings - Fork 30.4k
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-101892: Fix SystemError when a callable iterator call exhausts the iterator #101896
gh-101892: Fix SystemError when a callable iterator call exhausts the iterator #101896
Conversation
Updated Cython/objects/iterobject.c Line 217
It's good to coverage this case in tests. |
Added a test copied from the issue with readability changes. |
Objects/iterobject.c
Outdated
@@ -214,7 +214,7 @@ calliter_iternext(calliterobject *it) | |||
} | |||
|
|||
result = _PyObject_CallNoArgs(it->it_callable); | |||
if (result != NULL) { | |||
if (result != NULL && it->it_callable != NULL) { |
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.
Sorry, but this won't fix it. Notice the first if
statement in the function. If it->it_callable == NULL
is true, NULL
is returned. So it->it_callable != NULL
is already guaranteed at this point.
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.
What if we check it->it_sentinel != NULL
?
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.
It looks like NULL
is being passed to PyObject_RichCompareBool()
through it->it_sentinel
when it expects an object?
If we add the check
if (result != NULL && it->it_sentinel != NULL) {
and get rid of that Py_DECREF(result)
and place a new
Py_XDECREF(result);
just before return NULL;
Then the code in the issue will raise a StopIteration
(no longer SystemError
) and tests pass.
I'm not entirely sure if this is correct, TBH, but this is my guess.
Lib/test/test_iter.py
Outdated
return NO_MORE | ||
spam.need_reentrance = True | ||
spam.iterator = iter(spam, NO_MORE) | ||
next(spam.iterator) |
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.
What's the expected behaviour here? StopIteration
?
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.
Thank you for noticing the oversight! Fixed.
@workingpayload What do you think? Worth a try? |
Yeah! Why not? |
Lib/test/test_iter.py
Outdated
def spam(): | ||
if spam.need_reentrance: | ||
spam.need_reentrance = False | ||
list(spam.iterator) # Implicitly call ourselves |
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 evening (after getting access to my dev machine) I'll check whether the inner list()
is required to throw StopIteration
to trigger the bug. If no, I will simplify the test:
list(spam.iterator) # Implicitly call ourselves | |
try: | |
list(spam.iterator) # Implicitly call ourselves. | |
except StopIteration: | |
pass |
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 got it wrong. list()
cannot throw an exception because it returns a ready-to-use list (possibly empty) processing StopIteration
by itself.
LGTM. By the way PR title can be more meaningful. Ex: Fix SystemError when a callable iterator call exhausts the iterator. |
@kumaraditya303 Thank you, addressed. |
Thanks @workingpayload for the PR, and @kumaraditya303 for merging it 🌮🎉.. I'm working now to backport this PR to: 3.10, 3.11. |
Sorry, @workingpayload and @kumaraditya303, I could not cleanly backport this to |
GH-102418 is a backport of this pull request to the 3.11 branch. |
…usts the iterator (pythonGH-101896) (cherry picked from commit 705487c) Co-authored-by: Raj <51259329+workingpayload@users.noreply.github.com> Co-authored-by: Oleg Iarygin <oleg@arhadthedev.net>
…usts the iterator (python#101896) Co-authored-by: Oleg Iarygin <oleg@arhadthedev.net> (cherry picked from commit 705487c)
GH-102422 is a backport of this pull request to the 3.10 branch. |
@arhadthedev Thanks for the continued work on this! |
…usts the iterator (python#101896) Co-authored-by: Oleg Iarygin <oleg@arhadthedev.net>
* main: (21 commits) pythongh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives in sub interpreters module (python#102472) pythongh-95672: Fix versionadded indentation of get_pagesize in test.rst (pythongh-102455) pythongh-102416: Do not memoize incorrectly loop rules in the parser (python#102467) pythonGH-101362: Optimise PurePath(PurePath(...)) (pythonGH-101667) pythonGH-101362: Check pathlib.Path flavour compatibility at import time (pythonGH-101664) pythonGH-101362: Call join() only when >1 argument supplied to pathlib.PurePath() (python#101665) pythongh-102444: Fix minor bugs in `test_typing` highlighted by pyflakes (python#102445) pythonGH-102341: Improve the test function for pow (python#102342) Fix unused classes in a typing test (pythonGH-102437) pythongh-101979: argparse: fix a bug where parentheses in metavar argument of add_argument() were dropped (python#102318) pythongh-102356: Add thrashcan macros to filter object dealloc (python#102426) Move around example in to_bytes() to avoid confusion (python#101595) pythonGH-97546: fix flaky asyncio `test_wait_for_race_condition` test (python#102421) pythongh-96821: Add config option `--with-strict-overflow` (python#96823) pythongh-101992: update pstlib module documentation (python#102133) pythongh-63301: Set exit code when tabnanny CLI exits on error (python#7699) pythongh-101863: Fix wrong comments in EUC-KR codec (pythongh-102417) pythongh-102302 Micro-optimize `inspect.Parameter.__hash__` (python#102303) pythongh-102179: Fix `os.dup2` error reporting for negative fds (python#102180) pythongh-101892: Fix `SystemError` when a callable iterator call exhausts the iterator (python#101896) ...
* main: (37 commits) pythongh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives in sub interpreters module (python#102472) pythongh-95672: Fix versionadded indentation of get_pagesize in test.rst (pythongh-102455) pythongh-102416: Do not memoize incorrectly loop rules in the parser (python#102467) pythonGH-101362: Optimise PurePath(PurePath(...)) (pythonGH-101667) pythonGH-101362: Check pathlib.Path flavour compatibility at import time (pythonGH-101664) pythonGH-101362: Call join() only when >1 argument supplied to pathlib.PurePath() (python#101665) pythongh-102444: Fix minor bugs in `test_typing` highlighted by pyflakes (python#102445) pythonGH-102341: Improve the test function for pow (python#102342) Fix unused classes in a typing test (pythonGH-102437) pythongh-101979: argparse: fix a bug where parentheses in metavar argument of add_argument() were dropped (python#102318) pythongh-102356: Add thrashcan macros to filter object dealloc (python#102426) Move around example in to_bytes() to avoid confusion (python#101595) pythonGH-97546: fix flaky asyncio `test_wait_for_race_condition` test (python#102421) pythongh-96821: Add config option `--with-strict-overflow` (python#96823) pythongh-101992: update pstlib module documentation (python#102133) pythongh-63301: Set exit code when tabnanny CLI exits on error (python#7699) pythongh-101863: Fix wrong comments in EUC-KR codec (pythongh-102417) pythongh-102302 Micro-optimize `inspect.Parameter.__hash__` (python#102303) pythongh-102179: Fix `os.dup2` error reporting for negative fds (python#102180) pythongh-101892: Fix `SystemError` when a callable iterator call exhausts the iterator (python#101896) ...
Updated Cython/objects/iterobject.c Line 217