You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The issue is a stack exhaustion. Examples can be trivially made for any iterator that takes another iterator as argument: itertools.takewhile(), zip() in Python3, etc. etc.
It's just one of many places where CPython does a recursion without checking the recursion depth. CPython still works, based on the resonable assumption that doing such a recursion here is obscure.
Someone seriously bored could start with some C-based callgraph builder; or alternatively use PyPy, which finds such recursions automatically in its own source, and compare all places where a recursion check is inserted with the corresponding place in CPython. There are a large number of them (761, not counting the JIT), so be patient :-(
This patch didn't have my sign-off. Applying it was premature. It is a somewhat heavy handed fix that slows all the common cases at the expense of an exotic case.
It's just one of many places where CPython does a recursion
without checking the recursion depth. CPython still works,
based on the resonable assumption that doing such a recursion
here is obscure.
I agree with that assessment and am going to close this as something we can live with (or least have lived with successfully for a long time). AFAICT, this situation doesn't arise in practical code.
It is possible to slow down the language by adding a variant of recursion checks to every call to an iterator. But this just makes the language pay a code complexity cost and performance cost for something that doesn't really affect real users. People typically choose itertools for their speed (otherwise, plain generators can be clearer). We shouldn't work against the needs of those users.
A robust, clean, and performant solution wouldn't be easy but would likely involve some general purpose stack overflow protection that periodically makes sure there is enough stack remaining for C Python to function correctly.
Activity
alex commentedon Feb 14, 2012
http://paste.pocoo.org/show/550884/ will reliably segfault Python3 on all platforms (similar versions for Python2 using itertools work)
arigo commentedon Feb 14, 2012
The issue is a stack exhaustion. Examples can be trivially made for any iterator that takes another iterator as argument: itertools.takewhile(), zip() in Python3, etc. etc.
It's just one of many places where CPython does a recursion without checking the recursion depth. CPython still works, based on the resonable assumption that doing such a recursion here is obscure.
Someone seriously bored could start with some C-based callgraph builder; or alternatively use PyPy, which finds such recursions automatically in its own source, and compare all places where a recursion check is inserted with the corresponding place in CPython. There are a large number of them (761, not counting the JIT), so be patient :-(
alex commentedon Nov 9, 2012
Since the paste is dead:
serhiy-storchaka commentedon Mar 19, 2013
I'm trying to solve this issue (it seemed easy), but the bug is worse than expected. Python crashed even without iteration at all.
del it
And fixing a recursive deallocator is more harder than iterator.
What can we do if a deallocator raises RuntimeError due to maximum recursion depth exceeded.
amauryfa commentedon Mar 19, 2013
Py_TRASHCAN_SAFE_BEGIN/Py_TRASHCAN_SAFE_END macros can help:
http://hg.python.org/cpython/file/57c6435ca03b/Python/traceback.c#l44
serhiy-storchaka commentedon Mar 19, 2013
Thank you. Now I understand why this issue not happened with containers.
serhiy-storchaka commentedon Mar 19, 2013
Here is a patch which adds recursion limit checks to builtin and itertools recursive iterators.
amauryfa commentedon Mar 24, 2013
LGTM otherwise.
serhiy-storchaka commentedon Apr 6, 2013
Oh, I forgot to remove old tests when had moved them to special test class.
Indeed. Thank you.
python-dev commentedon Apr 6, 2013
New changeset aaaf36026511 by Serhiy Storchaka in branch '3.3':
Issue bpo-14010: Fix a crash when iterating or deleting deeply nested filters
http://hg.python.org/cpython/rev/aaaf36026511
New changeset 846bd418aee5 by Serhiy Storchaka in branch 'default':
Issue bpo-14010: Fix a crash when iterating or deleting deeply nested filters
http://hg.python.org/cpython/rev/846bd418aee5
rhettinger commentedon Apr 6, 2013
This patch didn't have my sign-off. Applying it was premature. It is a somewhat heavy handed fix that slows all the common cases at the expense of an exotic case.
11 remaining items
serhiy-storchaka commentedon Jul 11, 2015
See bpo-24606 for another instance of this in map().
serhiy-storchaka commentedon May 7, 2017
See bpo-30297 for yet one instance of this in starmap().
[-]deeply nested filter segfaults[/-][+]deeply nested itertools objects segfault[/+]rhettinger commentedon Aug 24, 2019
[Armin]
I agree with that assessment and am going to close this as something we can live with (or least have lived with successfully for a long time). AFAICT, this situation doesn't arise in practical code.
It is possible to slow down the language by adding a variant of recursion checks to every call to an iterator. But this just makes the language pay a code complexity cost and performance cost for something that doesn't really affect real users. People typically choose itertools for their speed (otherwise, plain generators can be clearer). We shouldn't work against the needs of those users.
A robust, clean, and performant solution wouldn't be easy but would likely involve some general purpose stack overflow protection that periodically makes sure there is enough stack remaining for C Python to function correctly.
markshannon commentedon Jul 29, 2026
This was fixed by #132280The stack overflow in dealloc was fixed by #132280, but the general issue remains.
We should fix this.