Reactos
at master 111 lines 3.1 kB view raw
1/*** 2*resetstk.c - Recover from Stack overflow. 3* 4* Copyright (c) Microsoft Corporation. All rights reserved. 5* 6*Purpose: 7* Defines the _resetstkoflw() function. 8* 9*******************************************************************************/ 10 11#include <corecrt_internal.h> 12#include <malloc.h> 13 14#define MIN_STACK_REQ_WINNT 2 15 16 17 18/*** 19* void _resetstkoflw(void) - Recovers from Stack Overflow 20* 21* Purpose: 22* Sets the guard page to its position before the stack overflow. 23* 24* Exit: 25* Returns nonzero on success, zero on failure 26* 27*******************************************************************************/ 28 29extern "C" int __cdecl _resetstkoflw() 30{ 31 LPBYTE pStack, pStackBase, pMaxGuard, pMinGuard; 32 MEMORY_BASIC_INFORMATION mbi; 33 SYSTEM_INFO si; 34 DWORD PageSize; 35 DWORD RegionSize; 36 DWORD flOldProtect; 37 ULONG StackSizeInBytes; 38 39 // Use _alloca() to get the current stack pointer 40#pragma warning(push) 41#pragma warning(disable:6255) 42 // prefast(6255): This alloca is safe and we do not want a __try here 43 pStack = (LPBYTE)_alloca(1); 44#pragma warning(pop) 45 46 // Find the base of the stack. 47 48 if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) { 49 return 0; 50 } 51 52 pStackBase = (LPBYTE)mbi.AllocationBase; 53 54 GetSystemInfo(&si); 55 PageSize = si.dwPageSize; 56 RegionSize = 0; 57 StackSizeInBytes = 0; // Indicate just querying 58 if (__acrt_SetThreadStackGuarantee(&StackSizeInBytes) && StackSizeInBytes > 0) { 59 RegionSize = StackSizeInBytes; 60 } 61 62#pragma warning(push) 63#pragma warning(disable:6255) 64 // Silence prefast about overflow/underflow 65 RegionSize = (RegionSize + PageSize - 1) & ~(PageSize - 1); 66#pragma warning(pop) 67 68 // 69 // If there is a stack guarantee (RegionSize nonzero), then increase 70 // our guard page size by 1 so that even a subsequent fault that occurs 71 // midway (instead of at the beginning) through the first guard page 72 // will have the extra page to preserve the guarantee. 73 // 74 75 if (RegionSize != 0) { 76 RegionSize += PageSize; 77 } 78 79 if (RegionSize < MIN_STACK_REQ_WINNT * PageSize) { 80 RegionSize = MIN_STACK_REQ_WINNT * PageSize; 81 } 82 83 // 84 // Find the page(s) just below where the stack pointer currently points. 85 // This is the highest potential guard page. 86 // 87 88 pMaxGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) 89 - RegionSize); 90 91 // 92 // If the potential guard page is too close to the start of the stack 93 // region, abandon the reset effort for lack of space. Win9x has a 94 // larger reserved stack requirement. 95 // 96 97 pMinGuard = pStackBase + PageSize; 98 99 if (pMaxGuard < pMinGuard) { 100 return 0; 101 } 102 103 // Set the new guard page just below the current stack page. 104 105 if (VirtualAlloc(pMaxGuard, RegionSize, MEM_COMMIT, PAGE_READWRITE) == nullptr || 106 VirtualProtect(pMaxGuard, RegionSize, PAGE_READWRITE | PAGE_GUARD, &flOldProtect) == 0) { 107 return 0; 108 } 109 110 return 1; 111}