Skip to content

Commit f74442f

Browse files
hsbtXrXr
authored andcommitted
win32: Use GetCurrentThreadStackLimits to set machine stack bounds
[Backport ruby#11438] VirtualQuery against a local variable address may return a region that does not span the whole thread stack when the interpreter is initialized deep in the stack, such as Ruby embedded in another application. stack_check() then misfires with a bogus SystemStackError.
1 parent 41d79e8 commit f74442f

1 file changed

Lines changed: 13 additions & 21 deletions

File tree

thread_win32.c

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -589,35 +589,27 @@ rb_native_cond_destroy(rb_nativethread_cond_t *cond)
589589
}
590590

591591

592-
#define CHECK_ERR(expr) \
593-
{if (!(expr)) {rb_bug("err: %lu - %s", GetLastError(), #expr);}}
594-
595-
COMPILER_WARNING_PUSH
596-
#if __has_warning("-Wmaybe-uninitialized")
597-
COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized)
592+
#if !defined(_WIN32_WINNT_WIN8) || _WIN32_WINNT < 0x602
593+
/* declared in processthreadsapi.h only when _WIN32_WINNT >= 0x0602,
594+
* but exported from kernel32.dll since Windows 8 */
595+
WINBASEAPI VOID WINAPI GetCurrentThreadStackLimits(PULONG_PTR, PULONG_PTR);
598596
#endif
599-
static inline SIZE_T
600-
query_memory_basic_info(PMEMORY_BASIC_INFORMATION mi, void *local_in_parent_frame)
601-
{
602-
return VirtualQuery(asan_get_real_stack_addr(local_in_parent_frame), mi, sizeof(*mi));
603-
}
604-
COMPILER_WARNING_POP
605597

606598
static void
607599
native_thread_init_stack(rb_thread_t *th, void *local_in_parent_frame)
608600
{
609-
MEMORY_BASIC_INFORMATION mi;
610-
char *base, *end;
611-
DWORD size, space;
601+
ULONG_PTR low, high;
602+
SIZE_T size, space;
612603

613-
CHECK_ERR(query_memory_basic_info(&mi, local_in_parent_frame));
614-
base = mi.AllocationBase;
615-
end = mi.BaseAddress;
616-
end += mi.RegionSize;
617-
size = end - base;
604+
/* VirtualQuery against the current stack pointer may return a region
605+
* that does not span the whole stack when the interpreter is
606+
* initialized deep in the stack, which makes stack_check() misfire.
607+
* [Bug #11438] */
608+
GetCurrentThreadStackLimits(&low, &high);
609+
size = high - low;
618610
space = size / 5;
619611
if (space > 1024*1024) space = 1024*1024;
620-
th->ec->machine.stack_start = (VALUE *)end - 1;
612+
th->ec->machine.stack_start = (VALUE *)high - 1;
621613
th->ec->machine.stack_maxsize = size - space;
622614
}
623615

0 commit comments

Comments
 (0)