@@ -442,6 +442,7 @@ int pthread_attr_destroy(pthread_attr_t *a)
442442void
443443_Py_InitializeRecursionLimits (PyThreadState * tstate )
444444{
445+ uintptr_t here_addr = _Py_get_machine_stack_pointer ();
445446 _PyThreadStateImpl * _tstate = (_PyThreadStateImpl * )tstate ;
446447#ifdef WIN32
447448 ULONG_PTR low , high ;
@@ -458,8 +459,8 @@ _Py_InitializeRecursionLimits(PyThreadState *tstate)
458459 _tstate -> c_stack_top = (uintptr_t )stack_addr ;
459460 _tstate -> c_stack_hard_limit = _tstate -> c_stack_top - stack_size ;
460461 _tstate -> c_stack_soft_limit = _tstate -> c_stack_hard_limit + _PyOS_STACK_MARGIN_BYTES ;
461- #else
462- uintptr_t here_addr = _Py_get_machine_stack_pointer () ;
462+ #else // other platform
463+ _tstate -> c_stack_top = 0 ;
463464/// XXX musl supports HAVE_PTHRED_GETATTR_NP, but the resulting stack size
464465/// (on alpine at least) is much smaller than expected and imposes undue limits
465466/// compared to the old stack size estimation. (We assume musl is not glibc.)
@@ -477,22 +478,31 @@ _Py_InitializeRecursionLimits(PyThreadState *tstate)
477478 if (err == 0 ) {
478479 uintptr_t base = ((uintptr_t )stack_addr ) + guard_size ;
479480 _tstate -> c_stack_top = base + stack_size ;
480- #ifdef _Py_THREAD_SANITIZER
481+ # ifdef _Py_THREAD_SANITIZER
481482 // Thread sanitizer crashes if we use a bit more than half the stack.
482483 _tstate -> c_stack_soft_limit = base + (stack_size / 2 );
483- #else
484+ # else
484485 _tstate -> c_stack_soft_limit = base + _PyOS_STACK_MARGIN_BYTES * 2 ;
485- #endif
486+ # endif
486487 _tstate -> c_stack_hard_limit = base + _PyOS_STACK_MARGIN_BYTES ;
487- assert (_tstate -> c_stack_soft_limit < here_addr );
488- assert (here_addr < _tstate -> c_stack_top );
488+ }
489+ # endif // musl
490+ #endif // platform-specific code
491+
492+ /* Check that we currently are inside the discovered stack.
493+ * gh-139653: Boost's make_fcontext (and presumably other stack-switching
494+ * mechanisms) may be incompatible with platform API.
495+ */
496+ if (_tstate -> c_stack_top
497+ && _tstate -> c_stack_soft_limit < here_addr
498+ && here_addr < _tstate -> c_stack_top
499+ ) {
489500 return ;
490501 }
491- # endif
502+ // Generic fallback
492503 _tstate -> c_stack_top = _Py_SIZE_ROUND_UP (here_addr , 4096 );
493504 _tstate -> c_stack_soft_limit = _tstate -> c_stack_top - Py_C_STACK_SIZE ;
494505 _tstate -> c_stack_hard_limit = _tstate -> c_stack_top - (Py_C_STACK_SIZE + _PyOS_STACK_MARGIN_BYTES );
495- #endif
496506}
497507
498508/* The function _Py_EnterRecursiveCallTstate() only calls _Py_CheckRecursiveCall()
0 commit comments