ntdll/tests: Add committed / reserved thread stack sizes tests.
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
258f7b3604
commit
94dcca8a0e
|
@ -237,14 +237,266 @@ static void test_NtAllocateVirtualMemory(void)
|
|||
ok(status == STATUS_INVALID_PARAMETER, "NtAllocateVirtualMemoryEx returned %08x\n", status);
|
||||
}
|
||||
|
||||
struct test_stack_size_thread_args
|
||||
{
|
||||
DWORD expect_committed;
|
||||
DWORD expect_reserved;
|
||||
};
|
||||
|
||||
static void force_stack_grow(void)
|
||||
{
|
||||
volatile int buffer[0x2000];
|
||||
buffer[0] = 0xdeadbeef;
|
||||
(void)buffer[0];
|
||||
}
|
||||
|
||||
#ifdef _WIN64
|
||||
static void force_stack_grow_small(void)
|
||||
{
|
||||
volatile int buffer[0x400];
|
||||
buffer[0] = 0xdeadbeef;
|
||||
(void)buffer[0];
|
||||
}
|
||||
#endif
|
||||
|
||||
static DWORD WINAPI test_stack_size_thread(void *ptr)
|
||||
{
|
||||
struct test_stack_size_thread_args *args = ptr;
|
||||
MEMORY_BASIC_INFORMATION mbi;
|
||||
NTSTATUS status;
|
||||
SIZE_T size, guard_size;
|
||||
DWORD committed, reserved;
|
||||
void *addr;
|
||||
#ifdef _WIN64
|
||||
DWORD prot;
|
||||
void *tmp;
|
||||
#endif
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
reserved = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->DeallocationStack;
|
||||
todo_wine ok( committed == args->expect_committed || broken(committed == 0x1000), "unexpected stack committed size %x, expected %x\n", committed, args->expect_committed );
|
||||
ok( reserved == args->expect_reserved, "unexpected stack reserved size %x, expected %x\n", reserved, args->expect_reserved );
|
||||
|
||||
addr = (char *)NtCurrentTeb()->DeallocationStack;
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.AllocationBase == NtCurrentTeb()->DeallocationStack, "unexpected AllocationBase %p, expected %p\n", mbi.AllocationBase, NtCurrentTeb()->DeallocationStack );
|
||||
ok( mbi.AllocationProtect == PAGE_READWRITE, "unexpected AllocationProtect %#x, expected %#x\n", mbi.AllocationProtect, PAGE_READWRITE );
|
||||
ok( mbi.BaseAddress == addr, "unexpected BaseAddress %p, expected %p\n", mbi.BaseAddress, addr );
|
||||
todo_wine ok( mbi.State == MEM_RESERVE, "unexpected State %#x, expected %#x\n", mbi.State, MEM_RESERVE );
|
||||
todo_wine ok( mbi.Protect == 0, "unexpected Protect %#x, expected %#x\n", mbi.Protect, 0 );
|
||||
ok( mbi.Type == MEM_PRIVATE, "unexpected Type %#x, expected %#x\n", mbi.Type, MEM_PRIVATE );
|
||||
|
||||
|
||||
force_stack_grow();
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
reserved = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->DeallocationStack;
|
||||
todo_wine ok( committed == 0x9000, "unexpected stack committed size %x, expected 9000\n", committed );
|
||||
ok( reserved == args->expect_reserved, "unexpected stack reserved size %x, expected %x\n", reserved, args->expect_reserved );
|
||||
|
||||
|
||||
/* reserved area shrinks whenever stack grows */
|
||||
|
||||
addr = (char *)NtCurrentTeb()->DeallocationStack;
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.AllocationBase == NtCurrentTeb()->DeallocationStack, "unexpected AllocationBase %p, expected %p\n", mbi.AllocationBase, NtCurrentTeb()->DeallocationStack );
|
||||
ok( mbi.AllocationProtect == PAGE_READWRITE, "unexpected AllocationProtect %#x, expected %#x\n", mbi.AllocationProtect, PAGE_READWRITE );
|
||||
ok( mbi.BaseAddress == addr, "unexpected BaseAddress %p, expected %p\n", mbi.BaseAddress, addr );
|
||||
todo_wine ok( mbi.State == MEM_RESERVE, "unexpected State %#x, expected %#x\n", mbi.State, MEM_RESERVE );
|
||||
todo_wine ok( mbi.Protect == 0, "unexpected Protect %#x, expected %#x\n", mbi.Protect, 0 );
|
||||
ok( mbi.Type == MEM_PRIVATE, "unexpected Type %#x, expected %#x\n", mbi.Type, MEM_PRIVATE );
|
||||
|
||||
guard_size = reserved - committed - mbi.RegionSize;
|
||||
ok( guard_size == 0x1000 || guard_size == 0x2000 || guard_size == 0x3000, "unexpected guard_size %I64x, expected 1000, 2000 or 3000\n", (UINT64)guard_size );
|
||||
|
||||
/* the commit area is initially preceded by guard pages */
|
||||
|
||||
addr = (char *)NtCurrentTeb()->DeallocationStack + mbi.RegionSize;
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.AllocationBase == NtCurrentTeb()->DeallocationStack, "unexpected AllocationBase %p, expected %p\n", mbi.AllocationBase, NtCurrentTeb()->DeallocationStack );
|
||||
ok( mbi.AllocationProtect == PAGE_READWRITE, "unexpected AllocationProtect %#x, expected %#x\n", mbi.AllocationProtect, PAGE_READWRITE );
|
||||
ok( mbi.BaseAddress == addr, "unexpected BaseAddress %p, expected %p\n", mbi.BaseAddress, addr );
|
||||
ok( mbi.RegionSize == guard_size, "unexpected RegionSize %I64x, expected 3000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
ok( mbi.Protect == (PAGE_READWRITE|PAGE_GUARD), "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE|PAGE_GUARD );
|
||||
ok( mbi.Type == MEM_PRIVATE, "unexpected Type %#x, expected %#x\n", mbi.Type, MEM_PRIVATE );
|
||||
|
||||
addr = (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.AllocationBase == NtCurrentTeb()->DeallocationStack, "unexpected AllocationBase %p, expected %p\n", mbi.AllocationBase, NtCurrentTeb()->DeallocationStack );
|
||||
ok( mbi.AllocationProtect == PAGE_READWRITE, "unexpected AllocationProtect %#x, expected %#x\n", mbi.AllocationProtect, PAGE_READWRITE );
|
||||
ok( mbi.BaseAddress == addr, "unexpected BaseAddress %p, expected %p\n", mbi.BaseAddress, addr );
|
||||
ok( mbi.RegionSize == committed, "unexpected RegionSize %I64x, expected %I64x\n", (UINT64)mbi.RegionSize, (UINT64)committed );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
ok( mbi.Protect == PAGE_READWRITE, "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE );
|
||||
ok( mbi.Type == MEM_PRIVATE, "unexpected Type %#x, expected %#x\n", mbi.Type, MEM_PRIVATE );
|
||||
|
||||
|
||||
#ifdef _WIN64
|
||||
/* setting a guard page shrinks stack automatically */
|
||||
|
||||
addr = (char *)NtCurrentTeb()->Tib.StackLimit + 0x2000;
|
||||
size = 0x1000;
|
||||
status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
|
||||
ok( !status, "NtAllocateVirtualMemory returned %08x\n", status );
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x6000, "unexpected stack committed size %x, expected 6000\n", committed );
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), (char *)addr - 0x2000, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.RegionSize == 0x2000, "unexpected RegionSize %I64x, expected 2000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
ok( mbi.Protect == PAGE_READWRITE, "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE );
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.RegionSize == 0x1000, "unexpected RegionSize %I64x, expected 1000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
ok( mbi.Protect == (PAGE_READWRITE|PAGE_GUARD), "unexpected Protect %#x, expected %#x\n", mbi.Protect, (PAGE_READWRITE|PAGE_GUARD) );
|
||||
|
||||
addr = (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
todo_wine ok( mbi.RegionSize == 0x6000, "unexpected RegionSize %I64x, expected 6000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
ok( mbi.Protect == PAGE_READWRITE, "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE );
|
||||
|
||||
|
||||
/* guard pages are restored as the stack grows back */
|
||||
|
||||
addr = (char *)NtCurrentTeb()->Tib.StackLimit + 0x4000;
|
||||
tmp = (char *)addr - guard_size - 0x1000;
|
||||
size = 0x1000;
|
||||
status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
|
||||
ok( !status, "NtAllocateVirtualMemory returned %08x\n", status );
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x1000, "unexpected stack committed size %x, expected 1000\n", committed );
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), tmp, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
todo_wine ok( mbi.RegionSize == guard_size + 0x1000, "unexpected RegionSize %I64x, expected %I64x\n", (UINT64)mbi.RegionSize, (UINT64)(guard_size + 0x1000) );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
todo_wine ok( mbi.Protect == PAGE_READWRITE, "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE );
|
||||
|
||||
force_stack_grow_small();
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x2000, "unexpected stack committed size %x, expected 2000\n", committed );
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), tmp, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.RegionSize == 0x1000, "unexpected RegionSize %I64x, expected 1000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
todo_wine ok( mbi.Protect == PAGE_READWRITE, "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE );
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), (char *)tmp + 0x1000, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.RegionSize == guard_size, "unexpected RegionSize %I64x, expected %I64x\n", (UINT64)mbi.RegionSize, (UINT64)guard_size );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
todo_wine ok( mbi.Protect == (PAGE_READWRITE|PAGE_GUARD), "unexpected Protect %#x, expected %#x\n", mbi.Protect, (PAGE_READWRITE|PAGE_GUARD) );
|
||||
|
||||
|
||||
/* forcing stack limit over guard pages still shrinks the stack on page fault */
|
||||
|
||||
addr = (char *)tmp + guard_size + 0x1000;
|
||||
size = 0x1000;
|
||||
status = NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size, MEM_COMMIT, PAGE_READWRITE | PAGE_GUARD );
|
||||
ok( !status, "NtAllocateVirtualMemory returned %08x\n", status );
|
||||
|
||||
NtCurrentTeb()->Tib.StackLimit = (char *)tmp;
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), (char *)tmp + 0x1000, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
todo_wine ok( mbi.RegionSize == guard_size + 0x1000, "unexpected RegionSize %I64x, expected %I64x\n", (UINT64)mbi.RegionSize, (UINT64)(guard_size + 0x1000) );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
todo_wine ok( mbi.Protect == (PAGE_READWRITE|PAGE_GUARD), "unexpected Protect %#x, expected %#x\n", mbi.Protect, (PAGE_READWRITE|PAGE_GUARD) );
|
||||
|
||||
force_stack_grow_small();
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x2000, "unexpected stack committed size %x, expected 2000\n", committed );
|
||||
|
||||
|
||||
/* it works with NtProtectVirtualMemory as well */
|
||||
|
||||
force_stack_grow();
|
||||
|
||||
addr = (char *)NtCurrentTeb()->Tib.StackLimit + 0x2000;
|
||||
size = 0x1000;
|
||||
status = NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READWRITE | PAGE_GUARD, &prot );
|
||||
ok( !status, "NtProtectVirtualMemory returned %08x\n", status );
|
||||
todo_wine ok( prot == PAGE_READWRITE, "unexpected prot %#x, expected %#x\n", prot, PAGE_READWRITE );
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x6000, "unexpected stack committed size %x, expected 6000\n", committed );
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), (char *)addr - 0x2000, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
todo_wine ok( mbi.RegionSize == 0x2000, "unexpected RegionSize %I64x, expected 2000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
todo_wine ok( mbi.Protect == PAGE_READWRITE, "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE );
|
||||
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
ok( mbi.RegionSize == 0x1000, "unexpected RegionSize %I64x, expected 1000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
ok( mbi.Protect == (PAGE_READWRITE|PAGE_GUARD), "unexpected Protect %#x, expected %#x\n", mbi.Protect, (PAGE_READWRITE|PAGE_GUARD) );
|
||||
|
||||
addr = (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
status = NtQueryVirtualMemory( NtCurrentProcess(), addr, MemoryBasicInformation, &mbi, sizeof(mbi), &size );
|
||||
ok( !status, "NtQueryVirtualMemory returned %08x\n", status );
|
||||
todo_wine ok( mbi.RegionSize == 0x6000, "unexpected RegionSize %I64x, expected 6000\n", (UINT64)mbi.RegionSize );
|
||||
ok( mbi.State == MEM_COMMIT, "unexpected State %#x, expected %#x\n", mbi.State, MEM_COMMIT );
|
||||
todo_wine ok( mbi.Protect == PAGE_READWRITE, "unexpected Protect %#x, expected %#x\n", mbi.Protect, PAGE_READWRITE );
|
||||
|
||||
|
||||
/* clearing the guard pages doesn't change StackLimit back */
|
||||
|
||||
force_stack_grow();
|
||||
|
||||
addr = (char *)NtCurrentTeb()->Tib.StackLimit + 0x2000;
|
||||
size = 0x1000;
|
||||
status = NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READWRITE | PAGE_GUARD, &prot );
|
||||
ok( !status, "NtProtectVirtualMemory returned %08x\n", status );
|
||||
todo_wine ok( prot == PAGE_READWRITE, "unexpected prot %#x, expected %#x\n", prot, PAGE_READWRITE );
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x6000, "unexpected stack committed size %x, expected 6000\n", committed );
|
||||
|
||||
status = NtProtectVirtualMemory( NtCurrentProcess(), &addr, &size, PAGE_READWRITE, &prot );
|
||||
ok( !status, "NtProtectVirtualMemory returned %08x\n", status );
|
||||
ok( prot == (PAGE_READWRITE | PAGE_GUARD), "unexpected prot %#x, expected %#x\n", prot, (PAGE_READWRITE | PAGE_GUARD) );
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x6000, "unexpected stack committed size %x, expected 6000\n", committed );
|
||||
|
||||
/* and as we messed with it and it now doesn't fault, it doesn't grow back either */
|
||||
|
||||
force_stack_grow();
|
||||
|
||||
committed = (char *)NtCurrentTeb()->Tib.StackBase - (char *)NtCurrentTeb()->Tib.StackLimit;
|
||||
todo_wine ok( committed == 0x6000, "unexpected stack committed size %x, expected 6000\n", committed );
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_RtlCreateUserStack(void)
|
||||
{
|
||||
IMAGE_NT_HEADERS *nt = RtlImageNtHeader( NtCurrentTeb()->Peb->ImageBaseAddress );
|
||||
struct test_stack_size_thread_args args;
|
||||
SIZE_T default_commit = nt->OptionalHeader.SizeOfStackCommit;
|
||||
SIZE_T default_reserve = nt->OptionalHeader.SizeOfStackReserve;
|
||||
INITIAL_TEB stack = {0};
|
||||
unsigned int i;
|
||||
NTSTATUS ret;
|
||||
HANDLE thread;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -298,6 +550,18 @@ static void test_RtlCreateUserStack(void)
|
|||
|
||||
ret = pRtlCreateUserStack(0x11000, 0x110000, 0, 0, 1, &stack);
|
||||
ok(ret == STATUS_INVALID_PARAMETER, "got %#x\n", ret);
|
||||
|
||||
args.expect_committed = 0x4000;
|
||||
args.expect_reserved = default_reserve;
|
||||
thread = CreateThread(NULL, 0x3f00, test_stack_size_thread, &args, 0, NULL);
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
|
||||
args.expect_committed = default_commit < 0x2000 ? 0x2000 : default_commit;
|
||||
args.expect_reserved = 0x400000;
|
||||
thread = CreateThread(NULL, 0x3ff000, test_stack_size_thread, &args, STACK_SIZE_PARAM_IS_A_RESERVATION, NULL);
|
||||
WaitForSingleObject(thread, INFINITE);
|
||||
CloseHandle(thread);
|
||||
}
|
||||
|
||||
static void test_NtMapViewOfSection(void)
|
||||
|
|
Loading…
Reference in New Issue