| OLD | NEW |
| (Empty) |
| 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 <stdlib.h> | |
| 12 #include <malloc.h> | |
| 13 #include <windows.h> | |
| 14 | |
| 15 #define MIN_STACK_REQ_WIN9X 17 | |
| 16 #define MIN_STACK_REQ_WINNT 2 | |
| 17 | |
| 18 #define _osplatform VER_PLATFORM_WIN32_NT | |
| 19 | |
| 20 /*** | |
| 21 * void _resetstkoflw() - Recovers from Stack Overflow | |
| 22 * | |
| 23 * Purpose: | |
| 24 * Sets the guard page to its position before the stack overflow. | |
| 25 * | |
| 26 * Exit: | |
| 27 * Returns nonzero on success, zero on failure | |
| 28 * | |
| 29 *******************************************************************************/ | |
| 30 | |
| 31 int _resetstkoflw() | |
| 32 { | |
| 33 LPBYTE pStack, pGuard, pStackBase, pMaxGuard, pMinGuard; | |
| 34 MEMORY_BASIC_INFORMATION mbi; | |
| 35 SYSTEM_INFO si; | |
| 36 DWORD PageSize; | |
| 37 DWORD flNewProtect; | |
| 38 DWORD flOldProtect; | |
| 39 | |
| 40 // Use _alloca() to get the current stack pointer | |
| 41 | |
| 42 pStack = _alloca(1); | |
| 43 | |
| 44 // Find the base of the stack. | |
| 45 | |
| 46 if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0) | |
| 47 return 0; | |
| 48 pStackBase = mbi.AllocationBase; | |
| 49 | |
| 50 // Find the page just below where the stack pointer currently points. | |
| 51 // This is the highest potential guard page. | |
| 52 | |
| 53 GetSystemInfo(&si); | |
| 54 PageSize = si.dwPageSize; | |
| 55 | |
| 56 pMaxGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1)) | |
| 57 - PageSize); | |
| 58 | |
| 59 // If the potential guard page is too close to the start of the stack | |
| 60 // region, abandon the reset effort for lack of space. Win9x has a | |
| 61 // larger reserved stack requirement. | |
| 62 | |
| 63 pMinGuard = pStackBase + ((_osplatform == VER_PLATFORM_WIN32_WINDOWS) | |
| 64 ? MIN_STACK_REQ_WIN9X | |
| 65 : MIN_STACK_REQ_WINNT) * PageSize; | |
| 66 | |
| 67 if (pMaxGuard < pMinGuard) | |
| 68 return 0; | |
| 69 | |
| 70 // On a non-Win9x system, do nothing if a guard page is already present, | |
| 71 // else set up the guard page to the bottom of the committed range, | |
| 72 // allowing for the reserved stack requirement. | |
| 73 // For Win9x, just set guard page below the current stack page. | |
| 74 | |
| 75 if (_osplatform != VER_PLATFORM_WIN32_WINDOWS) { | |
| 76 | |
| 77 // Find first block of committed memory in the stack region | |
| 78 | |
| 79 pGuard = pStackBase; | |
| 80 do { | |
| 81 if (VirtualQuery(pGuard, &mbi, sizeof mbi) == 0) | |
| 82 return 0; | |
| 83 pGuard = pGuard + mbi.RegionSize; | |
| 84 } while ((mbi.State & MEM_COMMIT) == 0); | |
| 85 pGuard = mbi.BaseAddress; | |
| 86 | |
| 87 // If first committed block is already marked as a guard page, | |
| 88 // there is nothing that needs to be done, so return success. | |
| 89 | |
| 90 if (mbi.Protect & PAGE_GUARD) | |
| 91 return 1; | |
| 92 | |
| 93 // Fail if the first committed block is above the highest potential | |
| 94 // guard page. Should never happen. | |
| 95 | |
| 96 if (pMaxGuard < pGuard) | |
| 97 return 0; | |
| 98 | |
| 99 // Make sure to leave enough room so the next overflow will have | |
| 100 // the proper reserved stack requirement available. | |
| 101 | |
| 102 if (pGuard < pMinGuard) | |
| 103 pGuard = pMinGuard; | |
| 104 | |
| 105 VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE); | |
| 106 } | |
| 107 else { | |
| 108 pGuard = pMaxGuard; | |
| 109 } | |
| 110 | |
| 111 // Enable the new guard page. | |
| 112 | |
| 113 flNewProtect = _osplatform == VER_PLATFORM_WIN32_WINDOWS | |
| 114 ? PAGE_NOACCESS | |
| 115 : PAGE_READWRITE | PAGE_GUARD; | |
| 116 | |
| 117 return VirtualProtect(pGuard, PageSize, flNewProtect, &flOldProtect); | |
| 118 } | |
| OLD | NEW |