-
-
Notifications
You must be signed in to change notification settings - Fork 31.6k
Stack overflow in repr of deeply nested dicts #76318
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
repr() of deeply nested dicts and dictviews can cause a stack overflow. >>> x = {}
>>> for i in range(100000):
... x = {1: x}
...
>>> repr(x)
Segmentation fault
>>> x = {}
>>> for i in range(100000):
... x = {1: x}
...
>>> repr(x.values())
Segmentation fault repr() of virtually all other deeply nested collections are guarded by using Py_EnterRecursiveCall(). >>> x = ()
>>> for i in range(100000):
... x = (x,)
...
>>> repr(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded while getting the repr of a tuple
>>> x = []
>>> for i in range(100000):
... x = [x]
...
>>> repr(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded while getting the repr of a list
>>> x = frozenset()
>>> for i in range(100000):
... x = frozenset({x})
...
>>> repr(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded while getting the repr of a list
>>> from collections import OrderedDict
>>> x = {}
>>> for i in range(100000):
... x = OrderedDict({1: x})
...
>>> repr(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded while getting the repr of a list
>>> from collections import deque
>>> x = deque()
>>> for i in range(100000):
... x = deque([x])
...
>>> repr(x)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RecursionError: maximum recursion depth exceeded while getting the repr of a list But the case of infinite recursion already is handled: >>> x = {}
>>> x[1] = x
>>> repr(x)
'{1: {...}}' Only finite but very deep recursion causes a crash. The one possible solution -- add Py_EnterRecursiveCall() in the implementation of dict.__repr__(), like it already is added in list.__repr__() and tuple.__repr__(). The more general solution -- add Py_EnterRecursiveCall() in PyObject_Repr(). In any case it is called before calling PyObject_Repr() for every item in the repr of most collections except dict. And it is already added in PyObject_Str(). Therefore adding it will not add much overhead, but can handle more corner cases. |
PR 4812 is an alternate fix for 3.6. It doesn't touch reprs of other types. |
The issue seems somewhat contrived but the fix looks fine to me. |
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: