Skip to content

Commit 7b03a5a

Browse files
markshannonmiss-islington
authored andcommitted
pythonGH-137573: Add test to check that the margin used for overflow protection is larger than the stack space used by the interpreter (pythonGH-137724)
(cherry picked from commit 16eae6d) Co-authored-by: Mark Shannon <[email protected]>
1 parent 460ad1a commit 7b03a5a

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

Lib/test/test_call.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
import _testlimitedcapi
1313
except ImportError:
1414
_testlimitedcapi = None
15+
try:
16+
import _testinternalcapi
17+
except ImportError:
18+
_testinternalcapi = None
1519
import struct
1620
import collections
1721
import itertools
@@ -1037,6 +1041,18 @@ def test_unexpected_keyword_suggestion_via_getargs(self):
10371041
@cpython_only
10381042
class TestRecursion(unittest.TestCase):
10391043

1044+
def test_margin_is_sufficient(self):
1045+
1046+
def get_sp():
1047+
return _testinternalcapi.get_stack_pointer()
1048+
1049+
this_sp = _testinternalcapi.get_stack_pointer()
1050+
lower_sp = _testcapi.pyobject_vectorcall(get_sp, (), ())
1051+
self.assertLess(lower_sp, this_sp)
1052+
# Add an (arbitrary) extra 25% for safety
1053+
safe_margin = (this_sp - lower_sp) * 5 / 4
1054+
self.assertLess(safe_margin, _testinternalcapi.get_stack_margin())
1055+
10401056
@skip_on_s390x
10411057
@unittest.skipIf(is_wasi and Py_DEBUG, "requires deep stack")
10421058
@skip_if_sanitizer("requires deep stack", thread=True)

Modules/_testinternalcapi.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,18 @@ get_c_recursion_remaining(PyObject *self, PyObject *Py_UNUSED(args))
125125
return PyLong_FromLong(remaining);
126126
}
127127

128+
static PyObject*
129+
get_stack_pointer(PyObject *self, PyObject *Py_UNUSED(args))
130+
{
131+
uintptr_t here_addr = _Py_get_machine_stack_pointer();
132+
return PyLong_FromSize_t(here_addr);
133+
}
134+
135+
static PyObject*
136+
get_stack_margin(PyObject *self, PyObject *Py_UNUSED(args))
137+
{
138+
return PyLong_FromSize_t(_PyOS_STACK_MARGIN_BYTES);
139+
}
128140

129141
static PyObject*
130142
test_bswap(PyObject *self, PyObject *Py_UNUSED(args))
@@ -2381,6 +2393,8 @@ static PyMethodDef module_functions[] = {
23812393
{"get_configs", get_configs, METH_NOARGS},
23822394
{"get_recursion_depth", get_recursion_depth, METH_NOARGS},
23832395
{"get_c_recursion_remaining", get_c_recursion_remaining, METH_NOARGS},
2396+
{"get_stack_pointer", get_stack_pointer, METH_NOARGS},
2397+
{"get_stack_margin", get_stack_margin, METH_NOARGS},
23842398
{"test_bswap", test_bswap, METH_NOARGS},
23852399
{"test_popcount", test_popcount, METH_NOARGS},
23862400
{"test_bit_length", test_bit_length, METH_NOARGS},

0 commit comments

Comments
 (0)