[2/2] kernel32/tests: Add tests for committing stack guard pages.
Sebastian Lackner
sebastian at fds-team.de
Sat Nov 28 13:07:41 CST 2015
Assembler code is based on the implementation for wine_call_on_stack.
Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
---
dlls/kernel32/tests/virtual.c | 76 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 76 insertions(+)
diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c
index e80ba38..da89df0 100644
--- a/dlls/kernel32/tests/virtual.c
+++ b/dlls/kernel32/tests/virtual.c
@@ -2048,6 +2048,81 @@ static void test_guard_page(void)
VirtualFree( base, 0, MEM_FREE );
}
+static DWORD WINAPI stack_commit_func( void *arg )
+{
+ volatile char *p = (char *)&p;
+
+ /* trigger all guard pages, to ensure that the pages are committed */
+ while (p >= (char *)pNtCurrentTeb()->DeallocationStack + 2 * 0x1000)
+ {
+ p[0] |= 0;
+ p -= 0x1000;
+ }
+
+ ok( arg == (void *)0xdeadbeef, "expected 0xdeadbeef, got %p\n", arg );
+ return 42;
+}
+
+static void test_stack_commit(void)
+{
+ static const char code_call_on_stack[] = {
+ 0x55, /* pushl %ebp */
+ 0x56, /* pushl %esi */
+ 0x89, 0xe6, /* movl %esp,%esi */
+ 0x8b, 0x4c, 0x24, 0x0c, /* movl 12(%esp),%ecx - func */
+ 0x8b, 0x54, 0x24, 0x10, /* movl 16(%esp),%edx - arg */
+ 0x8b, 0x44, 0x24, 0x14, /* movl 20(%esp),%eax - stack */
+ 0x83, 0xe0, 0xf0, /* andl $~15,%eax */
+ 0x83, 0xe8, 0x0c, /* subl $12,%eax */
+ 0x89, 0xc4, /* movl %eax,%esp */
+ 0x52, /* pushl %edx */
+ 0x31, 0xed, /* xorl %ebp,%ebp */
+ 0xff, 0xd1, /* call *%ecx */
+ 0x89, 0xf4, /* movl %esi,%esp */
+ 0x5e, /* popl %esi */
+ 0x5d, /* popl %ebp */
+ 0xc2, 0x0c, 0x00 }; /* ret $12 */
+
+ DWORD (WINAPI *call_on_stack)( DWORD (WINAPI *func)(void *), void *arg, void *stack );
+ void *old_stack, *old_stack_base, *old_stack_limit;
+ void *new_stack, *new_stack_base;
+ DWORD result;
+
+ if (!pNtCurrentTeb)
+ {
+ win_skip( "NtCurrentTeb not supported\n" );
+ return;
+ }
+
+ call_on_stack = VirtualAlloc( 0, 0x1000, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE );
+ ok( call_on_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
+ memcpy( call_on_stack, code_call_on_stack, sizeof(code_call_on_stack) );
+
+ /* allocate a new stack, only the first guard page is committed */
+ new_stack = VirtualAlloc( 0, 0x400000, MEM_RESERVE, PAGE_READWRITE );
+ ok( new_stack != NULL, "VirtualAlloc failed %u\n", GetLastError() );
+ new_stack_base = (char *)new_stack + 0x400000;
+ VirtualAlloc( (char *)new_stack_base - 0x1000, 0x1000, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
+
+ old_stack = pNtCurrentTeb()->DeallocationStack;
+ old_stack_base = pNtCurrentTeb()->Tib.StackBase;
+ old_stack_limit = pNtCurrentTeb()->Tib.StackLimit;
+
+ pNtCurrentTeb()->DeallocationStack = new_stack;
+ pNtCurrentTeb()->Tib.StackBase = new_stack_base;
+ pNtCurrentTeb()->Tib.StackLimit = new_stack_base;
+
+ result = call_on_stack( stack_commit_func, (void *)0xdeadbeef, new_stack_base );
+ ok( result == 42, "expected 42, got %u\n", result );
+
+ pNtCurrentTeb()->DeallocationStack = old_stack;
+ pNtCurrentTeb()->Tib.StackBase = old_stack_base;
+ pNtCurrentTeb()->Tib.StackLimit = old_stack_limit;
+
+ VirtualFree( new_stack, 0, MEM_FREE );
+ VirtualFree( call_on_stack, 0, MEM_FREE );
+}
+
DWORD num_execute_fault_calls;
static DWORD execute_fault_seh_handler( EXCEPTION_RECORD *rec, EXCEPTION_REGISTRATION_RECORD *frame,
@@ -3772,6 +3847,7 @@ START_TEST(virtual)
test_write_watch();
#ifdef __i386__
test_guard_page();
+ test_stack_commit();
/* The following tests should be executed as a last step, and in exactly this
* order, since ATL thunk emulation cannot be enabled anymore on Windows. */
test_atl_thunk_emulation( MEM_EXECUTE_OPTION_ENABLE );
--
2.6.2
More information about the wine-patches
mailing list