Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.9 KiB

  1. /***
  2. *resetstk.c - Recover from Stack overflow.
  3. *
  4. * Copyright (c) 1989-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Defines the _resetstkoflw() function.
  8. *
  9. *Revision History:
  10. * 12-10-99 GB Module Created
  11. * 04-17-01 PML Enable for Win9x, return success code (vs7#239962)
  12. * 06-04-01 PML Do nothing if guard page not missing, don't shrink
  13. * committed space (vs7#264306)
  14. * 04-25-02 PML Don't set guard page below pMinGuard (vs7#530044)
  15. *
  16. *******************************************************************************/
  17. #include <stdlib.h>
  18. #include <malloc.h>
  19. #include <windows.h>
  20. #define MIN_STACK_REQ_WIN9X 17
  21. #define MIN_STACK_REQ_WINNT 2
  22. /***
  23. * void _resetstkoflw(void) - Recovers from Stack Overflow
  24. *
  25. * Purpose:
  26. * Sets the guard page to its position before the stack overflow.
  27. *
  28. * Exit:
  29. * Returns nonzero on success, zero on failure
  30. *
  31. *******************************************************************************/
  32. #ifdef DOWNLEVEL
  33. #define _resetstkoflw _resetstkoflw_downlevel
  34. #endif
  35. int __cdecl _resetstkoflw(void)
  36. {
  37. LPBYTE pStack, pGuard, pStackBase, pMaxGuard, pMinGuard;
  38. MEMORY_BASIC_INFORMATION mbi;
  39. SYSTEM_INFO si;
  40. DWORD PageSize;
  41. DWORD flNewProtect;
  42. DWORD flOldProtect;
  43. // Use _alloca() to get the current stack pointer
  44. pStack = _alloca(1);
  45. // Find the base of the stack.
  46. if (VirtualQuery(pStack, &mbi, sizeof mbi) == 0)
  47. return 0;
  48. pStackBase = mbi.AllocationBase;
  49. // Find the page just below where the stack pointer currently points.
  50. // This is the highest potential guard page.
  51. GetSystemInfo(&si);
  52. PageSize = si.dwPageSize;
  53. pMaxGuard = (LPBYTE) (((DWORD_PTR)pStack & ~(DWORD_PTR)(PageSize - 1))
  54. - PageSize);
  55. // If the potential guard page is too close to the start of the stack
  56. // region, abandon the reset effort for lack of space. Win9x has a
  57. // larger reserved stack requirement.
  58. pMinGuard = pStackBase + ((_osplatform == VER_PLATFORM_WIN32_WINDOWS)
  59. ? MIN_STACK_REQ_WIN9X
  60. : MIN_STACK_REQ_WINNT) * PageSize;
  61. if (pMaxGuard < pMinGuard)
  62. return 0;
  63. // On a non-Win9x system, do nothing if a guard page is already present,
  64. // else set up the guard page to the bottom of the committed range,
  65. // allowing for the reserved stack requirement.
  66. // For Win9x, just set guard page below the current stack page.
  67. if (_osplatform != VER_PLATFORM_WIN32_WINDOWS) {
  68. // Find first block of committed memory in the stack region
  69. pGuard = pStackBase;
  70. do {
  71. if (VirtualQuery(pGuard, &mbi, sizeof mbi) == 0)
  72. return 0;
  73. pGuard = pGuard + mbi.RegionSize;
  74. } while ((mbi.State & MEM_COMMIT) == 0);
  75. pGuard = mbi.BaseAddress;
  76. // If first committed block is already marked as a guard page,
  77. // there is nothing that needs to be done, so return success.
  78. if (mbi.Protect & PAGE_GUARD)
  79. return 1;
  80. // Fail if the first committed block is above the highest potential
  81. // guard page. Should never happen.
  82. if (pMaxGuard < pGuard)
  83. return 0;
  84. // Make sure to leave enough room so the next overflow will have
  85. // the proper reserved stack requirement available.
  86. if (pGuard < pMinGuard)
  87. pGuard = pMinGuard;
  88. VirtualAlloc(pGuard, PageSize, MEM_COMMIT, PAGE_READWRITE);
  89. }
  90. else {
  91. pGuard = pMaxGuard;
  92. }
  93. // Enable the new guard page.
  94. flNewProtect = _osplatform == VER_PLATFORM_WIN32_WINDOWS
  95. ? PAGE_NOACCESS
  96. : PAGE_READWRITE | PAGE_GUARD;
  97. return VirtualProtect(pGuard, PageSize, flNewProtect, &flOldProtect);
  98. }