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
{{ message }}
Repository navigation
crash with unbounded recursion in except statement #86666
This program can work well on Python 3.5.2 and Python2.7 with the following output.
"Invalid Entry, try again"
However it will crash on Python3.9.0rc1, 3.10.0a2 with the following error message:
"
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized
Current thread 0x00007fc4b679b700 (most recent call first):
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 38 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
...
Aborted (core dumped)
"
The script contains the following line in the definition of status():
except status() as e:
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:
changed the title [-]status() crashes on Python3.9 and 3.10[/-][+]crash with unbounded recursion in except statement[/+]on Nov 29, 2020
vedgar commented on Nov 29, 2020
vedgarmannequin
Mannequin
More actions
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.
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.
As mentioned earlier I can reproduce this without calling os.fstat (python 3.9.1rc, macOS 10.15):
# ---
defstatus():
try:
1/0
except status():
pass
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).
Activity
xxm commentedon Nov 29, 2020
This program can work well on Python 3.5.2 and Python2.7 with the following output.
"Invalid Entry, try again"
However it will crash on Python3.9.0rc1, 3.10.0a2 with the following error message:
"
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow.
Python runtime state: initialized
Current thread 0x00007fc4b679b700 (most recent call first):
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 38 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
File "/home/xxm/Desktop/methodfuzzer/error/error1.py", line 39 in status
...
Aborted (core dumped)
"
ronaldoussoren commentedon Nov 29, 2020
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:
try:
1/0
except status():
pass
status()[-]status() crashes on Python3.9 and 3.10[/-][+]crash with unbounded recursion in except statement[/+][-]status() crashes on Python3.9 and 3.10[/-][+]crash with unbounded recursion in except statement[/+]vedgar commentedon Nov 29, 2020
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.)
ronaldoussoren commentedon Nov 29, 2020
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.
ericvsmith commentedon Nov 29, 2020
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.
ericvsmith commentedon Nov 29, 2020
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.
ronaldoussoren commentedon Nov 30, 2020
As mentioned earlier I can reproduce this without calling os.fstat (python 3.9.1rc, macOS 10.15):
# ---
except status():
pass
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).
ronaldoussoren commentedon Nov 30, 2020
See also bpo-42509
markshannon commentedon Nov 30, 2020
Ronald's test case also causes a Fatal Error on master.
2.7.18 produces the expected "RuntimeError: maximum recursion depth exceeded"
markshannon commentedon Dec 2, 2020
New changeset 4e7a69b by Mark Shannon in branch 'master':
bpo-42500: Fix recursion in or after except (GH-23568)
4e7a69b
ambv commentedon Mar 2, 2021
New changeset 8b795ab by Mark Shannon in branch '3.9':
bpo-42500: Fix recursion in or after except (GH-23568) (bpo-24501)
8b795ab
ambv commentedon Apr 4, 2021
New changeset c7b0fec by Gregory P. Smith in branch '3.9':
[3.9] bpo-43710: Rollback the 3.9 bpo-42500 fix, it broke the ABI in 3.9.3 (bpo-25179)
c7b0fec