ReactOS 0.4.15-dev-7924-g5949c20
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#include <pseh/pseh2.h>
11
12#ifdef _MSC_VER
13#pragma warning(disable : 4717) // disable warning about recursive function
14#endif
15
16static int iteration = 0;
20
21static
22void
24{
25 MEMORY_BASIC_INFORMATION MemoryBasicInfo;
27 char Buffer[0x500];
28
29 sprintf(Buffer, "Iteration %d.\n", iteration++);
30
33 &Buffer[0],
35 &MemoryBasicInfo,
36 sizeof(MemoryBasicInfo),
37 NULL);
39 /* This never changes */
41 /* Stack is committed one page at a time */
42 ok_ptr(MemoryBasicInfo.BaseAddress, (PVOID)PAGE_ROUND_DOWN(&Buffer[0]));
43 /* This is the protection of the memory when it was reserved. */
45 /* Windows commits the whole used stack at once, +2 pages. */
46#if 0
48#endif
49 /* This is the state of the queried address */
50 ok_long(MemoryBasicInfo.State, MEM_COMMIT);
51 /* This is the protection of the queried address */
52 ok_long(MemoryBasicInfo.Protect, PAGE_READWRITE);
53 /* Of course this is private memory. */
54 ok_long(MemoryBasicInfo.Type, MEM_PRIVATE);
55
56 LastStackAllocation = &Buffer[-0x500];
57
59}
60
61START_TEST(StackOverflow)
62{
64 MEMORY_BASIC_INFORMATION MemoryBasicInfo;
65
66 /* Get the base of the stack */
69 &Status,
71 &MemoryBasicInfo,
72 sizeof(MemoryBasicInfo),
73 NULL);
75 StackAllocationBase = MemoryBasicInfo.AllocationBase;
76 trace("Stack allocation base is %p.\n", StackAllocationBase);
77 StackSize = MemoryBasicInfo.RegionSize;
78
79 /* Check TEB attributes */
80 ok_ptr(NtCurrentTeb()->DeallocationStack, StackAllocationBase);
81 ok_ptr(NtCurrentTeb()->NtTib.StackBase, (PVOID)((ULONG_PTR)MemoryBasicInfo.BaseAddress + MemoryBasicInfo.RegionSize));
82#ifdef _WIN64
83 ok_ptr(NtCurrentTeb()->NtTib.StackLimit, (PVOID)((ULONG_PTR)MemoryBasicInfo.BaseAddress - 2 * PAGE_SIZE));
84#else
85 ok_ptr(NtCurrentTeb()->NtTib.StackLimit, (PVOID)((ULONG_PTR)MemoryBasicInfo.BaseAddress - PAGE_SIZE));
86#endif
87 trace("Guaranteed stack size is %lu.\n", NtCurrentTeb()->GuaranteedStackBytes);
88
89 /* Get its size */
94 &MemoryBasicInfo,
95 sizeof(MemoryBasicInfo),
96 NULL);
98
99 /* This is the complete stack size */
100 StackSize += MemoryBasicInfo.RegionSize;
101 trace("Stack size is 0x%lx.\n", StackSize);
102
103 trace("Stack limit %p, stack base %p.\n", NtCurrentTeb()->NtTib.StackLimit, NtCurrentTeb()->NtTib.StackBase);
104
105 /* Take a look at what is beyond the stack limit */
108 NtCurrentTeb()->NtTib.StackLimit,
110 &MemoryBasicInfo,
111 sizeof(MemoryBasicInfo),
112 NULL);
114
115 ok_ptr(MemoryBasicInfo.BaseAddress, NtCurrentTeb()->NtTib.StackLimit);
116 ok_ptr(MemoryBasicInfo.AllocationBase, StackAllocationBase);
117 ok_long(MemoryBasicInfo.AllocationProtect, PAGE_READWRITE);
118#ifdef _WIN64
119 ok_long(MemoryBasicInfo.RegionSize, 3 * PAGE_SIZE);
120#else
121 ok_long(MemoryBasicInfo.RegionSize, 2 * PAGE_SIZE);
122#endif
123 ok_long(MemoryBasicInfo.State, MEM_COMMIT);
124 ok_long(MemoryBasicInfo.Protect, PAGE_READWRITE);
125 ok_long(MemoryBasicInfo.Type, MEM_PRIVATE);
126
127 /* Accessing below stack limit is OK, as long as we don't starve the reserved space. */
129 {
130 volatile CHAR* Pointer = (PVOID)((ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit - PAGE_SIZE / 2);
131 CHAR Value = *Pointer;
132 (void)Value;
134 }
136 {
138 }
139 _SEH2_END;
141
143 {
145 }
147 {
148 trace("Exception after %d iteration.\n", iteration);
150 }
151 _SEH2_END;
152
154
155 /* Windows lets 2 pages between the reserved memory and the smallest possible stack address */
157#ifdef _WIN64
159#else
161#endif
162
163 /* And in fact, this is the true condition of the stack overflow */
165
166 trace("Stack limit %p, stack base %p.\n", NtCurrentTeb()->NtTib.StackLimit, NtCurrentTeb()->NtTib.StackBase);
167
168 /* Of course, accessing above the stack limit is OK. */
170 {
171 volatile CHAR* Pointer = (PVOID)((ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit + PAGE_SIZE / 2);
172 CHAR Value = *Pointer;
173 (void)Value;
175 }
177 {
179 }
180 _SEH2_END;
182
183 /* But once stack is starved, it's starved. */
185 {
186 volatile CHAR* Pointer = (PVOID)((ULONG_PTR)NtCurrentTeb()->NtTib.StackLimit - PAGE_SIZE / 2);
187 CHAR Value = *Pointer;
188 (void)Value;
190 }
192 {
193 trace("Exception after %d iteration.\n", iteration);
195 }
196 _SEH2_END;
198}
static PVOID StackAllocationBase
Definition: StackOverflow.c:17
static ULONG StackSize
Definition: StackOverflow.c:19
static PVOID LastStackAllocation
Definition: StackOverflow.c:18
static int iteration
Definition: StackOverflow.c:16
static void infinite_recursive(void)
Definition: StackOverflow.c:23
#define ok_ntstatus(status, expected)
Definition: atltest.h:135
#define ok_long(expression, result)
Definition: atltest.h:133
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define START_TEST(x)
Definition: atltest.h:75
#define ok_ptr(expression, result)
Definition: atltest.h:108
LONG NTSTATUS
Definition: precomp.h:26
Definition: bufpool.h:45
#define NULL
Definition: types.h:112
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
Status
Definition: gdiplustypes.h:25
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define NtCurrentTeb
#define sprintf(buf, format,...)
Definition: sprintf.c:55
@ MemoryBasicInformation
Definition: mmtypes.h:183
#define PAGE_ROUND_DOWN(x)
Definition: mmtypes.h:36
#define PAGE_READWRITE
Definition: nt_native.h:1304
#define MEM_PRIVATE
Definition: nt_native.h:1318
#define NtCurrentProcess()
Definition: nt_native.h:1657
#define MEM_COMMIT
Definition: nt_native.h:1313
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:4409
#define STATUS_STACK_OVERFLOW
Definition: ntstatus.h:489
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define STATUS_SUCCESS
Definition: shellext.h:65
void * PVOID
Definition: typedefs.h:50
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
char CHAR
Definition: xmlstorage.h:175