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.

281 lines
6.1 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. alloca.c
  5. Abstract:
  6. This module implements a safe stack-based allocator with fallback to the heap.
  7. Author:
  8. Jonathan Schwartz (JSchwart) 16-Mar-2001
  9. Revision History:
  10. --*/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <malloc.h> // _resetstkoflw()
  16. #include <alloca.h>
  17. //
  18. // Globals used to control SafeAlloca behavior
  19. //
  20. SIZE_T g_ulMaxStackAllocSize;
  21. SIZE_T g_ulAdditionalProbeSize;
  22. SAFEALLOC_ALLOC_PROC g_pfnAllocate;
  23. SAFEALLOC_FREE_PROC g_pfnFree;
  24. //
  25. // Local function declarations
  26. //
  27. PVOID
  28. SafeAllocaAllocateFromHeap(
  29. SIZE_T Size
  30. );
  31. VOID
  32. SafeAllocaFreeToHeap(
  33. PVOID BaseAddress
  34. );
  35. //+-------------------------------------------------------------------------
  36. //
  37. // Function: SafeAllocaInitialize
  38. //
  39. // Synopsis: Initialize globals used to control SafeAlloca behavior
  40. //
  41. // Effects:
  42. //
  43. // Arguments:
  44. //
  45. // Requires:
  46. //
  47. // Returns:
  48. //
  49. // Notes: Must be called before SafeAlloca is used to allocate space
  50. //
  51. //--------------------------------------------------------------------------
  52. VOID
  53. SafeAllocaInitialize(
  54. IN OPTIONAL SIZE_T ulMaxStackAllocSize,
  55. IN OPTIONAL SIZE_T ulAdditionalProbeSize,
  56. IN OPTIONAL SAFEALLOC_ALLOC_PROC pfnAllocate,
  57. IN OPTIONAL SAFEALLOC_FREE_PROC pfnFree
  58. )
  59. {
  60. PIMAGE_NT_HEADERS NtHeaders = NULL;
  61. PPEB Peb = NtCurrentPeb();
  62. //
  63. // Make sure this is the first and only time the init is being called for this
  64. // binary (either DLL or EXE since this is a code LIB). Otherwise, we could
  65. // end up with the free routine after memory is allocated using a completely
  66. // unrelated allocator.
  67. //
  68. ASSERT((g_pfnAllocate == NULL || g_pfnAllocate == pfnAllocate
  69. || (g_pfnAllocate == SafeAllocaAllocateFromHeap && pfnAllocate == NULL))
  70. &&
  71. (g_pfnFree == NULL || g_pfnFree == pfnFree
  72. || (g_pfnFree == SafeAllocaFreeToHeap && pfnFree == NULL)));
  73. if (NtCurrentPeb()->BeingDebugged)
  74. {
  75. //
  76. // Usermode debugger is attached to this process, which can cause issues
  77. // when the first-chance overflow exception on stack probes is caught by
  78. // the debugger rather than the probe exception handler. Force all
  79. // allocations to the heap.
  80. //
  81. g_ulMaxStackAllocSize = 0;
  82. }
  83. else if (ulMaxStackAllocSize == SAFEALLOCA_USE_DEFAULT)
  84. {
  85. //
  86. // Default is stack size from the image header
  87. //
  88. NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress);
  89. if (NtHeaders == NULL)
  90. {
  91. //
  92. // This shouldn't happen -- it implies the binary is bad.
  93. // Set the default to force heap allocations only.
  94. //
  95. ASSERT(NtHeaders != NULL);
  96. g_ulMaxStackAllocSize = 0;
  97. }
  98. else
  99. {
  100. g_ulMaxStackAllocSize = NtHeaders->OptionalHeader.SizeOfStackCommit;
  101. }
  102. }
  103. else
  104. {
  105. g_ulMaxStackAllocSize = ulMaxStackAllocSize;
  106. }
  107. if (ulAdditionalProbeSize == SAFEALLOCA_USE_DEFAULT)
  108. {
  109. //
  110. // Default is stack size from the image header
  111. //
  112. if (NtHeaders == NULL)
  113. {
  114. NtHeaders = RtlImageNtHeader(Peb->ImageBaseAddress);
  115. }
  116. if (NtHeaders == NULL)
  117. {
  118. //
  119. // This shouldn't happen -- it implies the binary is bad.
  120. // Set the default to force heap allocations only.
  121. //
  122. ASSERT(NtHeaders != NULL);
  123. g_ulAdditionalProbeSize = 0xffffffff;
  124. }
  125. else
  126. {
  127. g_ulAdditionalProbeSize = NtHeaders->OptionalHeader.SizeOfStackCommit;
  128. }
  129. }
  130. else
  131. {
  132. g_ulAdditionalProbeSize = ulAdditionalProbeSize;
  133. }
  134. if (pfnAllocate == NULL)
  135. {
  136. g_pfnAllocate = SafeAllocaAllocateFromHeap;
  137. }
  138. else
  139. {
  140. g_pfnAllocate = pfnAllocate;
  141. }
  142. if (pfnFree == NULL)
  143. {
  144. g_pfnFree = SafeAllocaFreeToHeap;
  145. }
  146. else
  147. {
  148. g_pfnFree = pfnFree;
  149. }
  150. }
  151. //+-------------------------------------------------------------------------
  152. //
  153. // Function: SafeAllocaAllocateFromHeap
  154. //
  155. // Synopsis: Default fallback heap allocator for SafeAlloca
  156. //
  157. // Effects:
  158. //
  159. // Arguments:
  160. //
  161. // Requires:
  162. //
  163. // Returns:
  164. //
  165. // Notes:
  166. //
  167. //--------------------------------------------------------------------------
  168. PVOID
  169. SafeAllocaAllocateFromHeap(
  170. SIZE_T Size
  171. )
  172. {
  173. return RtlAllocateHeap(RtlProcessHeap(), 0, Size);
  174. }
  175. //+-------------------------------------------------------------------------
  176. //
  177. // Function: SafeAllocaFreeToHeap
  178. //
  179. // Synopsis: Default fallback heap free routine for SafeAlloca
  180. //
  181. // Effects:
  182. //
  183. // Arguments:
  184. //
  185. // Requires:
  186. //
  187. // Returns:
  188. //
  189. // Notes:
  190. //
  191. //--------------------------------------------------------------------------
  192. VOID
  193. SafeAllocaFreeToHeap(
  194. PVOID BaseAddress
  195. )
  196. {
  197. RtlFreeHeap(RtlProcessHeap(), 0, BaseAddress);
  198. }
  199. //+-------------------------------------------------------------------------
  200. //
  201. // Function: VerifyStackAvailable
  202. //
  203. // Synopsis: Routine to probe the stack to ensure the allocation size
  204. // plus additional probe size is available.
  205. //
  206. // Effects:
  207. //
  208. // Arguments:
  209. //
  210. // Requires:
  211. //
  212. // Returns:
  213. //
  214. // Notes:
  215. //
  216. //--------------------------------------------------------------------------
  217. BOOL
  218. VerifyStackAvailable(
  219. SIZE_T Size
  220. )
  221. {
  222. BOOL fStackAvailable = TRUE;
  223. __try
  224. {
  225. PVOID p = _alloca(Size);
  226. }
  227. __except ((EXCEPTION_STACK_OVERFLOW == GetExceptionCode()) ?
  228. EXCEPTION_EXECUTE_HANDLER :
  229. EXCEPTION_CONTINUE_SEARCH)
  230. {
  231. fStackAvailable = FALSE;
  232. _resetstkoflw();
  233. }
  234. return fStackAvailable;
  235. }