Skip to content

Commit 7260a9b

Browse files
committed
increase limits and use builtin functions to get stack pointer
1 parent 52b27d6 commit 7260a9b

File tree

6 files changed

+20
-17
lines changed

6 files changed

+20
-17
lines changed

Include/internal/pycore_ceval.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,18 @@ extern void _PyEval_DeactivateOpCache(void);
193193

194194
/* --- _Py_EnterRecursiveCall() ----------------------------------------- */
195195

196-
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
196+
static inline uintptr_t
197+
_Py_get_machine_stack_pointer(void) {
198+
#if defined(__GNUC__) || defined(__clang__)
199+
return (uintptr_t)__builtin_frame_address(0);
200+
#else
197201
char here;
198-
uintptr_t here_addr = (uintptr_t)&here;
202+
return (uintptr_t)&here;
203+
#endif
204+
}
205+
206+
static inline int _Py_MakeRecCheck(PyThreadState *tstate) {
207+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
199208
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
200209
return here_addr < _tstate->c_stack_soft_limit;
201210
}
@@ -226,8 +235,7 @@ static inline void _Py_LeaveRecursiveCallTstate(PyThreadState *tstate) {
226235
PyAPI_FUNC(void) _Py_InitializeRecursionLimits(PyThreadState *tstate);
227236

228237
static inline int _Py_ReachedRecursionLimit(PyThreadState *tstate) {
229-
char here;
230-
uintptr_t here_addr = (uintptr_t)&here;
238+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
231239
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
232240
if (here_addr > _tstate->c_stack_soft_limit) {
233241
return 0;

Lib/test/list_tests.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_repr(self):
6464
@skip_emscripten_stack_overflow()
6565
def test_repr_deep(self):
6666
a = self.type2test([])
67-
for i in range(150_000):
67+
for i in range(200_000):
6868
a = self.type2test([a])
6969
self.assertRaises(RecursionError, repr, a)
7070

Lib/test/test_compile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ def test_compiler_recursion_limit(self):
715715
# Compiler frames are small
716716
limit = 100
717717
fail_depth = limit * 1500
718-
crash_depth = limit * 3000
718+
crash_depth = limit * 5000
719719
success_depth = limit
720720

721721
def check_limit(prefix, repeated, mode="single"):

Lib/test/test_json/test_recursion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def test_highly_nested_objects_decoding(self):
8787
def test_highly_nested_objects_encoding(self):
8888
# See #12051
8989
l, d = [], {}
90-
for x in range(100000):
90+
for x in range(200_000):
9191
l, d = [l], {'k':d}
9292
with self.assertRaises(RecursionError):
9393
with support.infinite_recursion(5000):

Modules/_testinternalcapi.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,7 @@ static PyObject*
115115
get_c_recursion_remaining(PyObject *self, PyObject *Py_UNUSED(args))
116116
{
117117
PyThreadState *tstate = _PyThreadState_GET();
118-
char here;
119-
uintptr_t here_addr = (uintptr_t)&here;
118+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
120119
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
121120
int remaining = (int)((here_addr - _tstate->c_stack_soft_limit)/PYOS_STACK_MARGIN_BYTES * 50);
122121
return PyLong_FromLong(remaining);

Python/ceval.c

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,7 @@ Py_SetRecursionLimit(int new_limit)
307307
int
308308
_Py_ReachedRecursionLimitWithMargin(PyThreadState *tstate, int margin_count)
309309
{
310-
char here;
311-
uintptr_t here_addr = (uintptr_t)&here;
310+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
312311
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
313312
if (here_addr > _tstate->c_stack_soft_limit + margin_count * PYOS_STACK_MARGIN_BYTES) {
314313
return 0;
@@ -322,8 +321,7 @@ _Py_ReachedRecursionLimitWithMargin(PyThreadState *tstate, int margin_count)
322321
void
323322
_Py_EnterRecursiveCallUnchecked(PyThreadState *tstate)
324323
{
325-
char here;
326-
uintptr_t here_addr = (uintptr_t)&here;
324+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
327325
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
328326
if (here_addr < _tstate->c_stack_hard_limit) {
329327
Py_FatalError("Unchecked stack overflow.");
@@ -360,8 +358,7 @@ _Py_InitializeRecursionLimits(PyThreadState *tstate)
360358
_tstate->c_stack_hard_limit = ((uintptr_t)low) + guarantee + PYOS_STACK_MARGIN_BYTES;
361359
_tstate->c_stack_soft_limit = _tstate->c_stack_hard_limit + PYOS_STACK_MARGIN_BYTES;
362360
#else
363-
char here;
364-
uintptr_t here_addr = (uintptr_t)&here;
361+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
365362
# if defined(HAVE_PTHREAD_GETATTR_NP)
366363
size_t stack_size, guard_size;
367364
void *stack_addr;
@@ -392,8 +389,7 @@ int
392389
_Py_CheckRecursiveCall(PyThreadState *tstate, const char *where)
393390
{
394391
_PyThreadStateImpl *_tstate = (_PyThreadStateImpl *)tstate;
395-
char here;
396-
uintptr_t here_addr = (uintptr_t)&here;
392+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
397393
assert(_tstate->c_stack_soft_limit != 0);
398394
if (_tstate->c_stack_hard_limit == 0) {
399395
_Py_InitializeRecursionLimits(tstate);

0 commit comments

Comments
 (0)