ReactOS  0.4.15-dev-985-gd905dd5
StackOverflow.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS api tests
3  * LICENSE: GPL - See COPYING in the top level directory
4  * PURPOSE: Test for stack overflow
5  * PROGRAMMER: Jérôme Gardou
6  */
7 
8 #include "precomp.h"
9 
10 #ifdef _MSC_VER
11 #pragma warning(disable : 4717) // disable warning about recursive function
12 #endif
13 
14 static int iteration = 0;
18 
19 static
20 void
22 {
23  MEMORY_BASIC_INFORMATION MemoryBasicInfo;
25  char Buffer[0x500];
26 
27  sprintf(Buffer, "Iteration %d.\n", iteration++);
28 
31  &Buffer[0],
33  &MemoryBasicInfo,
34  sizeof(MemoryBasicInfo),
35  NULL);
37  /* This never changes */
38  ok_ptr(MemoryBasicInfo.AllocationBase, StackAllocationBase);
39  /* Stack is committed one page at a time */
40  ok_ptr(MemoryBasicInfo.BaseAddress, (PVOID)PAGE_ROUND_DOWN(&Buffer[0]));
41  /* This is the protection of the memory when it was reserved. */
42  ok_long(MemoryBasicInfo.AllocationProtect, PAGE_READWRITE);
43  /* Windows commits the whole used stack at once, +2 pages. */
44 #if 0
46 #endif
47  /* This is the state of the queried address */
48  ok_long(MemoryBasicInfo.State, MEM_COMMIT);
49  /* This is the protection of the queried address */
50  ok_long(MemoryBasicInfo.Protect, PAGE_READWRITE);
51  /* Of course this is private memory. */
52  ok_long(MemoryBasicInfo.Type, MEM_PRIVATE);
53 
54  LastStackAllocation = &Buffer[-0x500];
55 
57 }
58 
59 START_TEST(StackOverflow)
60 {
62  MEMORY_BASIC_INFORMATION MemoryBasicInfo;
63 
64  /* Get the base of the stack */
67  &Status,
69  &MemoryBasicInfo,
70  sizeof(MemoryBasicInfo),
71  NULL);
73  StackAllocationBase = MemoryBasicInfo.AllocationBase;
74  trace("Stack allocation base is %p.\n", StackAllocationBase);
75  StackSize = MemoryBasicInfo.RegionSize;
76 
77  /* Check TEB attributes */
78  ok_ptr(NtCurrentTeb()->DeallocationStack, StackAllocationBase);
79  ok_ptr(NtCurrentTeb()->NtTib.StackBase, (PVOID)((ULONG_PTR)MemoryBasicInfo.BaseAddress + MemoryBasicInfo.RegionSize));
80  ok_ptr(NtCurrentTeb()->NtTib.StackLimit, (PVOID)((ULONG_PTR)MemoryBasicInfo.BaseAddress - PAGE_SIZE));
81  trace("Guaranteed stack size is %lu.\n", NtCurrentTeb()->GuaranteedStackBytes);
82 
83  /* Get its size */
88  &MemoryBasicInfo,
89  sizeof(MemoryBasicInfo),
90  NULL);
92 
93  /* This is the complete stack size */
94  StackSize += MemoryBasicInfo.RegionSize;
95  trace("Stack size is 0x%lx.\n", StackSize);
96 
97  trace("Stack limit %p, stack base %p.\n", NtCurrentTeb()->NtTib.StackLimit, NtCurrentTeb()->NtTib.StackBase);
98 
99  /* Take a look at what is beyond the stack limit */
102  NtCurrentTeb()->NtTib.StackLimit,
104  &MemoryBasicInfo,
105  sizeof(MemoryBasicInfo),
106  NULL);
108 
109  ok_ptr(MemoryBasicInfo.BaseAddress, NtCurrentTeb()->NtTib.StackLimit);
110  ok_ptr(MemoryBasicInfo.AllocationBase, StackAllocationBase);
111  ok_long(MemoryBasicInfo.AllocationProtect, PAGE_READWRITE);
112  ok_long(MemoryBasicInfo.RegionSize, 2 * PAGE_SIZE);
113  ok_long(MemoryBasicInfo.State, MEM_COMMIT);
114  ok_long(MemoryBasicInfo.Protect, PAGE_READWRITE);
115  ok_long(MemoryBasicInfo.Type, MEM_PRIVATE);
116 
117  /* Accessing below stack limit is OK, as long as we don't starve the reserved space. */
118  _SEH2_TRY
119  {
120  volatile CHAR* Pointer = (PVOID)((ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit - PAGE_SIZE / 2);
121  CHAR Value = *Pointer;
122  (void)Value;
124  }
126  {
128  }
129  _SEH2_END;
131 
132  _SEH2_TRY
133  {
135  }
137  {
138  trace("Exception after %d iteration.\n", iteration);
140  }
141  _SEH2_END;
142 
144 
145  /* Windows lets 2 pages between the reserved memory and the smallest possible stack address */
148 
149  /* And in fact, this is the true condition of the stack overflow */
150  ok_ptr(NtCurrentTeb()->NtTib.StackLimit, (PVOID)((ULONG_PTR)StackAllocationBase + PAGE_SIZE));
151 
152  trace("Stack limit %p, stack base %p.\n", NtCurrentTeb()->NtTib.StackLimit, NtCurrentTeb()->NtTib.StackBase);
153 
154  /* Of course, accessing above the stack limit is OK. */
155  _SEH2_TRY
156  {
157  volatile CHAR* Pointer = (PVOID)((ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit + PAGE_SIZE / 2);
158  CHAR Value = *Pointer;
159  (void)Value;
161  }
163  {
165  }
166  _SEH2_END;
168 
169  /* But once stack is starved, it's starved. */
170  _SEH2_TRY
171  {
172  volatile CHAR* Pointer = (PVOID)((ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit - PAGE_SIZE / 2);
173  CHAR Value = *Pointer;
174  (void)Value;
176  }
178  {
179  trace("Exception after %d iteration.\n", iteration);
181  }
182  _SEH2_END;
184 }
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
char CHAR
Definition: xmlstorage.h:175
LONG NTSTATUS
Definition: precomp.h:26
static int iteration
Definition: StackOverflow.c:14
static ULONG StackSize
Definition: StackOverflow.c:17
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
NTSTATUS NTAPI NtQueryVirtualMemory(IN HANDLE ProcessHandle, IN PVOID BaseAddress, IN MEMORY_INFORMATION_CLASS MemoryInformationClass, OUT PVOID MemoryInformation, IN SIZE_T MemoryInformationLength, OUT PSIZE_T ReturnLength)
Definition: virtual.c:4284
#define ok_ptr(expression, result)
Definition: atltest.h:108
#define ok_long(expression, result)
Definition: atltest.h:133
#define MEM_COMMIT
Definition: nt_native.h:1313
IN UCHAR Value
Definition: halp.h:394
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static PVOID StackAllocationBase
Definition: StackOverflow.c:15
START_TEST(StackOverflow)
Definition: StackOverflow.c:59
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define trace
Definition: atltest.h:70
#define MEM_PRIVATE
Definition: nt_native.h:1318
static void infinite_recursive(void)
Definition: StackOverflow.c:21
static PVOID LastStackAllocation
Definition: StackOverflow.c:16
Status
Definition: gdiplustypes.h:24
#define PAGE_SIZE
Definition: env_spec_w32.h:49
_SEH2_END
Definition: create.c:4400
FORCEINLINE struct _TEB * NtCurrentTeb(VOID)
Definition: psfuncs.h:420
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define ok(value,...)
Definition: atltest.h:57
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:489
#define ok_ntstatus(status, expected)
Definition: atltest.h:135
unsigned int ULONG
Definition: retypes.h:1
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
return STATUS_SUCCESS
Definition: btrfs.c:3014
#define PAGE_READWRITE
Definition: nt_native.h:1304