Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112/****resetstk.c - Recover from Stack overflow.** Copyright (c) Microsoft Corporation. All rights reserved.**Purpose:* Defines the _resetstkoflw() function.********************************************************************************/
#include <corecrt_internal.h>#include <malloc.h>
#define MIN_STACK_REQ_WINNT 2
/**** void _resetstkoflw(void) - Recovers from Stack Overflow** Purpose:* Sets the guard page to its position before the stack overflow.** Exit:* Returns nonzero on success, zero on failure********************************************************************************/
extern "C" int __cdecl _resetstkoflw(){ LPBYTE pStack, pStackBase, pMaxGuard, pMinGuard; MEMORY_BASIC_INFORMATION mbi; SYSTEM_INFO si; DWORD PageSize; DWORD RegionSize; DWORD flOldProtect; ULONG StackSizeInBytes;
// Use _alloca() to get the current stack pointer#pragma warning(push)#pragma warning(disable:6255) // prefast(6255): This alloca is safe and we do not want a __try here pStack = (LPBYTE)_alloca(1);#pragma warning(pop)
// Find the base of the stack.
if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) { return 0; }
pStackBase = (LPBYTE)mbi.AllocationBase;
GetSystemInfo(&si); PageSize = si.dwPageSize; RegionSize = 0; StackSizeInBytes = 0; // Indicate just querying if (__acrt_SetThreadStackGuarantee(&StackSizeInBytes) && StackSizeInBytes > 0) { RegionSize = StackSizeInBytes; }
#pragma warning(push)#pragma warning(disable:6255) // Silence prefast about overflow/underflow RegionSize = (RegionSize + PageSize - 1) & ~(PageSize - 1);#pragma warning(pop)
// // If there is a stack guarantee (RegionSize nonzero), then increase // our guard page size by 1 so that even a subsequent fault that occurs // midway (instead of at the beginning) through the first guard page // will have the extra page to preserve the guarantee. //
if (RegionSize != 0) { RegionSize += PageSize; }
if (RegionSize < MIN_STACK_REQ_WINNT * PageSize) { RegionSize = MIN_STACK_REQ_WINNT * PageSize; }
// // Find the page(s) just below where the stack pointer currently points. // This is the highest potential guard page. //
pMaxGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) - RegionSize);
// // If the potential guard page is too close to the start of the stack // region, abandon the reset effort for lack of space. Win9x has a // larger reserved stack requirement. //
pMinGuard = pStackBase + PageSize;
if (pMaxGuard < pMinGuard) { return 0; }
// Set the new guard page just below the current stack page.
if (VirtualAlloc(pMaxGuard, RegionSize, MEM_COMMIT, PAGE_READWRITE) == nullptr || VirtualProtect(pMaxGuard, RegionSize, PAGE_READWRITE | PAGE_GUARD, &flOldProtect) == 0) { return 0; }
return 1;}