From 451763ba3b5c77497b56c833fa7fa3b6ee49d79f Mon Sep 17 00:00:00 2001 From: David Roman Date: Mon, 16 Mar 2026 21:12:08 -0400 Subject: [PATCH] fix: auto-update stack_top on thread/fiber context switch in js_check_stack_overflow When the runtime is called from a different thread or fiber than the one that captured stack_top, the stack pointer comparison produces false positives. This happens in any M:N threading model (green threads, fibers, coroutines) where each execution context has its own stack at an unrelated address. Detect this by checking if sp falls outside the expected stack range. If so, call JS_UpdateStackTop() to re-anchor before comparing. Zero overhead on the common single-thread path (unlikely branch). Genuine stack overflows are still detected correctly after re-anchoring. --- quickjs.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/quickjs.c b/quickjs.c index e30d393..4f16f40 100644 --- a/quickjs.c +++ b/quickjs.c @@ -1638,6 +1638,17 @@ static inline BOOL js_check_stack_overflow(JSRuntime *rt, size_t alloca_size) { uintptr_t sp; sp = js_get_stack_pointer() - alloca_size; + /* Detect when the runtime is being called from a different thread or + fiber than the one that set stack_top. In M:N threading models + (green threads, fibers, coroutines), each execution context has its + own stack at an unrelated address. If sp is outside the expected + range, re-anchor stack_top to the current stack before checking. + A genuine overflow has sp just below stack_limit; a context switch + has sp in a completely different address range. */ + if (unlikely(sp > rt->stack_top || sp + rt->stack_size < rt->stack_limit)) { + JS_UpdateStackTop(rt); + sp = js_get_stack_pointer() - alloca_size; + } return unlikely(sp < rt->stack_limit); } #endif