-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
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
crash with unbounded recursion in except statement #86666
Comments
This program can work well on Python 3.5.2 and Python2.7 with the following output. However it will crash on Python3.9.0rc1, 3.10.0a2 with the following error message: Current thread 0x00007fc4b679b700 (most recent call first): |
The crash is not nice, but.... The script contains the following line in the definition of status():
That will cause unbounded recursion when os.fstat raises an exception, which likely happens here. You probably want to catch OSError (or os.error) instead. This scriptlet is a smaller reproduction of the problem: def status(): try: except status(): status() |
Recursion limit is probably set too high, but nonetheless, the program is nonsensical, the line 39 especially. The reason for difference in behavior is that RecursionError is caught by blank except in the earlier Pythons, while it crashes the stack in later ones. In any case, it's almost certain this isn't what you wanted to write. (And yet another reason to remove blank except from Python: it abuse to correct use ratio is probably over two orders of magnitude.) |
The value of the recursion limit is not relevant here, I get the same crash when I set the recursion limit to 100 (in my reproducer scriptlet). There might be a missing recursion level check in the exception handling machinery though, self-recursion in an except-clause is rather unusual. But that's just a blind guess, I haven't though much about what is supposed to happen here. |
Here's the smallest reproducer I could come up with. It fails on Windows with 3.9 native(compiled locally) (Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow), works (raises RecursionError) with cygwin 3.8.3. import os
def status():
for fd in range(4):
try:
st = os.fstat(fd)
except status() as e:
pass
status() |
Note that changing the os.fstat line to just "raise OSError()" no longer causes the "Fatal Python error", but rather gives the expected recursion exception. Here's a shorter version that causes the fatal error in Windows native 3.9, cygwin 3.8.3, and Fedora Linux 3.7.7. So this isn't new with 3.9. import os
def status():
try:
st = os.fstat(4)
except status() as e:
pass
status() |
As mentioned earlier I can reproduce this without calling os.fstat (python 3.9.1rc, macOS 10.15): # --- def status():
try:
1/0 except status(): status()
# The crash happens both with the default recursion limit as well with a recursion limit of 10. Setting the recursion limit doesn't seem to have an effect on what's happening (in both cases I get a long traceback). |
See also bpo-42509 |
Ronald's test case also causes a Fatal Error on master. 2.7.18 produces the expected "RuntimeError: maximum recursion depth exceeded" |
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: