@@ -2446,6 +2446,58 @@ module_get_gc_hooks(PyObject *self, PyObject *arg)
24462446 return result ;
24472447}
24482448
2449+
2450+ static void
2451+ check_threadstate_set_stack_protection (PyThreadState * tstate ,
2452+ void * start , size_t size )
2453+ {
2454+ assert (PyUnstable_ThreadState_SetStackProtection (tstate , start , size ) == 0 );
2455+ assert (!PyErr_Occurred ());
2456+
2457+ _PyThreadStateImpl * ts = (_PyThreadStateImpl * )tstate ;
2458+ assert (ts -> c_stack_top == (uintptr_t )start + size );
2459+ assert (ts -> c_stack_hard_limit <= ts -> c_stack_soft_limit );
2460+ assert (ts -> c_stack_soft_limit < ts -> c_stack_top );
2461+ }
2462+
2463+
2464+ static PyObject *
2465+ test_threadstate_set_stack_protection (PyObject * self , PyObject * Py_UNUSED (args ))
2466+ {
2467+ PyThreadState * tstate = PyThreadState_GET ();
2468+ _PyThreadStateImpl * ts = (_PyThreadStateImpl * )tstate ;
2469+ assert (!PyErr_Occurred ());
2470+
2471+ uintptr_t init_base = ts -> c_stack_init_base ;
2472+ size_t init_top = ts -> c_stack_init_top ;
2473+
2474+ // Test the minimum stack size
2475+ size_t size = _PyOS_MIN_STACK_SIZE ;
2476+ void * start = (void * )(_Py_get_machine_stack_pointer () - size );
2477+ check_threadstate_set_stack_protection (tstate , start , size );
2478+
2479+ // Test a larger size
2480+ size = 7654321 ;
2481+ assert (size > _PyOS_MIN_STACK_SIZE );
2482+ start = (void * )(_Py_get_machine_stack_pointer () - size );
2483+ check_threadstate_set_stack_protection (tstate , start , size );
2484+
2485+ // Test invalid size (too small)
2486+ size = 5 ;
2487+ start = (void * )(_Py_get_machine_stack_pointer () - size );
2488+ assert (PyUnstable_ThreadState_SetStackProtection (tstate , start , size ) == -1 );
2489+ assert (PyErr_ExceptionMatches (PyExc_ValueError ));
2490+ PyErr_Clear ();
2491+
2492+ // Test PyUnstable_ThreadState_ResetStackProtection()
2493+ PyUnstable_ThreadState_ResetStackProtection (tstate );
2494+ assert (ts -> c_stack_init_base == init_base );
2495+ assert (ts -> c_stack_init_top == init_top );
2496+
2497+ Py_RETURN_NONE ;
2498+ }
2499+
2500+
24492501static PyMethodDef module_functions [] = {
24502502 {"get_configs" , get_configs , METH_NOARGS },
24512503 {"get_recursion_depth" , get_recursion_depth , METH_NOARGS },
@@ -2556,6 +2608,8 @@ static PyMethodDef module_functions[] = {
25562608 {"simple_pending_call ", simple_pending_call , METH_O },
25572609 {"set_vectorcall_nop ", set_vectorcall_nop , METH_O },
25582610 {"module_get_gc_hooks ", module_get_gc_hooks , METH_O },
2611+ {"test_threadstate_set_stack_protection ",
2612+ test_threadstate_set_stack_protection , METH_NOARGS },
25592613 {NULL, NULL } /* sentinel */
25602614};
25612615
0 commit comments