mirror of
https://github.com/python/cpython.git
synced 2025-09-27 02:39:58 +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)
|
# define _Py_MakeRecCheck(x) (++(x) > _Py_CheckRecursionLimit)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_STACKCHECK
|
#define _Py_MakeEndRecCheck(x) \
|
||||||
# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50)
|
(--(x) < ((_Py_CheckRecursionLimit > 100) \
|
||||||
#else
|
? (_Py_CheckRecursionLimit - 50) \
|
||||||
# define _Py_MakeEndRecCheck(x) (--(x) < _Py_CheckRecursionLimit - 50)
|
: (3 * (_Py_CheckRecursionLimit >> 2))))
|
||||||
#endif
|
|
||||||
|
|
||||||
#define Py_ALLOW_RECURSION \
|
#define Py_ALLOW_RECURSION \
|
||||||
do { unsigned char _old = PyThreadState_GET()->recursion_critical;\
|
do { unsigned char _old = PyThreadState_GET()->recursion_critical;\
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
import unittest, test.support
|
import unittest, test.support
|
||||||
import sys, io, os
|
import sys, io, os
|
||||||
import struct
|
import struct
|
||||||
|
import subprocess
|
||||||
|
import textwrap
|
||||||
|
|
||||||
class SysModuleTest(unittest.TestCase):
|
class SysModuleTest(unittest.TestCase):
|
||||||
|
|
||||||
|
@ -155,6 +157,46 @@ class SysModuleTest(unittest.TestCase):
|
||||||
self.assertEqual(sys.getrecursionlimit(), 10000)
|
self.assertEqual(sys.getrecursionlimit(), 10000)
|
||||||
sys.setrecursionlimit(oldlimit)
|
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):
|
def test_getwindowsversion(self):
|
||||||
if hasattr(sys, "getwindowsversion"):
|
if hasattr(sys, "getwindowsversion"):
|
||||||
v = sys.getwindowsversion()
|
v = sys.getwindowsversion()
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 3.1 alpha 2?
|
||||||
Core and Builtins
|
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
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
@ -24,8 +27,6 @@ What's New in Python 3.1 alpha 1
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
=======
|
|
||||||
|
|
||||||
- The io module has been reimplemented in C for speed.
|
- The io module has been reimplemented in C for speed.
|
||||||
|
|
||||||
- Give dict views an informative __repr__.
|
- Give dict views an informative __repr__.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue