mirror of
https://github.com/python/cpython.git
synced 2025-07-24 03:35:53 +00:00
Issue #5392: when a very low recursion limit was set, the interpreter would
abort with a fatal error after the recursion limit was hit twice.
This commit is contained in:
parent
ae2dbe2543
commit
652e7076fe
3 changed files with 49 additions and 7 deletions
|
@ -92,11 +92,10 @@ PyAPI_DATA(int) _Py_CheckRecursionLimit;
|
|||
# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
|
||||
#endif
|
||||
|
||||
#ifdef USE_STACKCHECK
|
||||
# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50)
|
||||
#else
|
||||
# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50)
|
||||
#endif
|
||||
#define _Py_MakeEndRecCheck(x) \
|
||||
(--(x) < ((_Py_CheckRecursionLimit > 100) \
|
||||
? (_Py_CheckRecursionLimit - 50) \
|
||||
: (3 * (_Py_CheckRecursionLimit >> 2))))
|
||||
|
||||
#define Py_ALLOW_RECURSION \
|
||||
do { unsigned char _old = PyThreadState_GET()->recursion_critical;\
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
import unittest, test.support
|
||||
import sys, io, os
|
||||
import struct
|
||||
import subprocess
|
||||
import textwrap
|
||||
|
||||
class SysModuleTest(unittest.TestCase):
|
||||
|
||||
|
@ -155,6 +157,46 @@ class SysModuleTest(unittest.TestCase):
|
|||
self.assertEqual(sys.getrecursionlimit(), 10000)
|
||||
sys.setrecursionlimit(oldlimit)
|
||||
|
||||
def test_recursionlimit_recovery(self):
|
||||
# NOTE: this test is slightly fragile in that it depends on the current
|
||||
# recursion count when executing the test being low enough so as to
|
||||
# trigger the recursion recovery detection in the _Py_MakeEndRecCheck
|
||||
# macro (see ceval.h).
|
||||
oldlimit = sys.getrecursionlimit()
|
||||
def f():
|
||||
f()
|
||||
try:
|
||||
for i in (50, 1000):
|
||||
# Issue #5392: stack overflow after hitting recursion limit twice
|
||||
sys.setrecursionlimit(i)
|
||||
self.assertRaises(RuntimeError, f)
|
||||
self.assertRaises(RuntimeError, f)
|
||||
finally:
|
||||
sys.setrecursionlimit(oldlimit)
|
||||
|
||||
def test_recursionlimit_fatalerror(self):
|
||||
# A fatal error occurs if a second recursion limit is hit when recovering
|
||||
# from a first one.
|
||||
code = textwrap.dedent("""
|
||||
import sys
|
||||
|
||||
def f():
|
||||
try:
|
||||
f()
|
||||
except RuntimeError:
|
||||
f()
|
||||
|
||||
sys.setrecursionlimit(%d)
|
||||
f()""")
|
||||
for i in (50, 1000):
|
||||
sub = subprocess.Popen([sys.executable, '-c', code % i],
|
||||
stderr=subprocess.PIPE)
|
||||
err = sub.communicate()[1]
|
||||
self.assertTrue(sub.returncode, sub.returncode)
|
||||
self.assertTrue(
|
||||
b"Fatal Python error: Cannot recover from stack overflow" in err,
|
||||
err)
|
||||
|
||||
def test_getwindowsversion(self):
|
||||
if hasattr(sys, "getwindowsversion"):
|
||||
v = sys.getwindowsversion()
|
||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 3.1 alpha 2?
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
- Issue #5392: when a very low recursion limit was set, the interpreter would
|
||||
abort with a fatal error after the recursion limit was hit twice.
|
||||
|
||||
Library
|
||||
-------
|
||||
|
||||
|
@ -24,8 +27,6 @@ What's New in Python 3.1 alpha 1
|
|||
Core and Builtins
|
||||
-----------------
|
||||
|
||||
=======
|
||||
|
||||
- The io module has been reimplemented in C for speed.
|
||||
|
||||
- Give dict views an informative __repr__.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue