-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
integer overflow in iterator object #67128
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
Comments
I found an interger overflow in the standard iterator object (Objects/iterobject.c) The Here is an example: import sys
class Seq:
def __getitem__(self, item):
print("[-] Asked for item at <{0}>".format(item))
return 0
s = Seq()
i = iter(s)
# Manually set `it_index` to PY_SSIZE_T_MAX without a loop
i.__setstate__(sys.maxsize)
next(i)
[-] Asked for item at <9223372036854775807>
next(i)
[-] Asked for item at <-9223372036854775808> I would be really interested in writing a patch but first I wanted to discuss the expected behaviour and fix. The iterator could stop after Or the same technique used in |
Yes it is a bug. iter_iternext() must raises an OverflowError if it->it_index is equal to PY_SSIZE_T_MAX. |
I think OverflowError is good for maintained releases, but for 3.5 Clement's idea with long index looks attractive to me. In any case an exception should be raised for negative argument in __setstate__(). Let split this issue on two parts. First fix the bug by raising exceptions, and then add long index (if anyone will need it). |
What is your use case? |
Something like range(). I agree that it is very unlike to encounter this |
Here is a first try for a patch. There are two points I am not sure about:
|
You should not rely on undefined behaviour: check if the index is greater You must always raise an error, not hide it in a second call to next (raise |
Just PY_SSIZET_MAX. Added other comments on Rietveld (look the email in the Spam folder). |
Thanks for the comments. Just one question:
Why should __setstate__ check for PY_SSIZE_T_MAX (throwing OverflowError when unpickling) if the check will be done when calling next on the resulting iterator ? |
__setstate__ should check that an index is not negative. All values from 0 to PY_SSIZE_T_MAX are acceptable. |
Ah, __setstate__ already handles negative indices. Then the patch LGTM. |
I would think that the PY_SSIZE_T_MAX check belongs inside the: if (result != NULL) {
it->it_index++;
return result;
} just before the increment which could cause the overflow. Also, PY_SSIZE_T_MAX is a valid value to pass to PySequence_GetItem(), so it shouldn't be blocked unless necessary. |
This doesn't matter because next() will raise an exception if it_index == PY_SSIZE_T_MAX in any case. The code should be changed much more to allow yielding an item with index PY_SSIZE_T_MAX, use other (negative) signal value and change the behavior of __setstate__ for negative values. |
I agree with you, that's why my first path was checking at the next call if it->it_index had overflowed. But then it relies on undefined behaviour.
If we raise the OverflowError when it->it_index really overflow (just after the getitem PY_SSIZE_T_MAX). |
I prefer to raise an OverflowError *before* calling |
You do realize that this error will be very rare and therefore inconsequential. |
The real question is: why would you call the iterator for a new value if it will be discarded anyway ? I think it could be very misleading to see _getitem__ being called and have an OverflowError being raised afterward. |
Is it necessary to raise when it_index is PY_SSIZE_T_MAX? An alternative is to set it_index to -1 when there would be overflow and raise an exception on the next call to next(). That way a virtual sequence with PY_SSIZE_T_MAX-1 items would still work (instead of failing unexpectedly). |
Actually with PY_SSIZE_T_MAX+1 items (indices from 0 to PY_SSIZE_T_MAX inclusive). If Raymond insists I can write more complicated patch, but I don't think that we should complicate the code for this pretty hypotetical case. I'm for committing issue22939v2.patch. |
After a few months, I am back to you on this issue. |
If Raymond will not stop me, I'll commit the patch tomorrow. |
New changeset d6179accca20 by Serhiy Storchaka in branch '2.7': New changeset 7fa2f4afcf5a by Serhiy Storchaka in branch '3.4': New changeset f23533fa6afa by Serhiy Storchaka in branch 'default': |
Thank you for your contribution Clement. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: