From 7f208124c9f83084a992ee09cd38a524ebaebdf6 Mon Sep 17 00:00:00 2001 From: Serge Gautherie <32623169+SergeGautherie@users.noreply.github.com> Date: Sat, 17 Mar 2018 17:30:01 +0100 Subject: [PATCH] [NTDLL_APITEST] Fix/Extend ApiTest NtAllocateVirtualMemory (#207) * Fix 1 failure on both WS03 and ReactOS. * Create CheckSomeDefaultAddresses(), with additional checks. * Update license header. * ROSTESTS-297 --- .../apitests/ntdll/NtAllocateVirtualMemory.c | 204 ++++++++++++++++-- 1 file changed, 181 insertions(+), 23 deletions(-) diff --git a/modules/rostests/apitests/ntdll/NtAllocateVirtualMemory.c b/modules/rostests/apitests/ntdll/NtAllocateVirtualMemory.c index d1a73cc9a5a..aae94052e6b 100644 --- a/modules/rostests/apitests/ntdll/NtAllocateVirtualMemory.c +++ b/modules/rostests/apitests/ntdll/NtAllocateVirtualMemory.c @@ -1,8 +1,11 @@ /* - * PROJECT: ReactOS API Tests - * LICENSE: GPLv2+ - See COPYING in the top level directory - * PURPOSE: Stress Test for virtual memory allocation - * PROGRAMMER: Thomas Faber + * PROJECT: ReactOS API Tests + * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+) + * PURPOSE: Test for NtAllocateVirtualMemory + * COPYRIGHT: Copyright 2011 Thomas Faber + * Copyright 2013 Timo Kreuzer + * Copyright 2015 Jérôme Gardou + * Copyright 2018 Serge Gautherie */ #include "precomp.h" @@ -562,39 +565,194 @@ CheckAdjacentVADs() } -#define RUNS 32 - -START_TEST(NtAllocateVirtualMemory) +static +VOID +CheckSomeDefaultAddresses(VOID) { - PVOID Mem1, Mem2; - SIZE_T Size1, Size2; - ULONG i; NTSTATUS Status; + PVOID BaseAddress; + SIZE_T Size; - CheckAlignment(); - CheckAdjacentVADs(); + // NULL. + + /* Reserve memory dynamically, not at 0x00000000 */ + BaseAddress = NULL; + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_READWRITE); + ok_ntstatus(Status, STATUS_SUCCESS); + ok(BaseAddress != 0x00000000, "Unexpected BaseAddress = 0x00000000\n"); + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + + // 0x00000000, 64k: Free. + + /* Reserve and commit memory at 0x00000000, after round down */ + BaseAddress = UlongToPtr(0x00000000 + 0x0FFF); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); + ok_ntstatus(Status, STATUS_SUCCESS); + ok_ptr(BaseAddress, 0x00000000); + + // Double-check that it is not forbidden "in order to catch null pointer accesses". + StartSeh() + *(int*)UlongToPtr(0x00000000) = 1; + EndSeh(STATUS_SUCCESS) + + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + + /* Reserve memory above 0x00000000 */ + BaseAddress = UlongToPtr(0x00000000 + 0x1000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_READWRITE); + ok_ntstatus(Status, STATUS_SUCCESS); + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + + /* The following checks assume very default addresses, + * no address space layout randomization (ASLR). */ +#ifdef _WIN64 + ok(FALSE, "ToDo, 64-bit: Check/Adapt 32-bit results\n"); +#endif - /* Reserve memory below 0x10000 */ - Mem1 = UlongToPtr(0xf000); - Size1 = 0x1000; + // 0x00010000, 4k: Private Data. + // 0x00011000, 60k: Unusable. + + /* Reserve memory below 0x00010000 */ + BaseAddress = UlongToPtr(0x00010000 - 0x1000); + Size = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), - &Mem1, + &BaseAddress, 0, - &Size1, + &Size, MEM_RESERVE, PAGE_READWRITE); - ok_ntstatus(Status, STATUS_INVALID_PARAMETER_2); + ok_ntstatus(Status, STATUS_SUCCESS); + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); - /* Reserve memory at 0x10000 */ - Mem1 = UlongToPtr(0x10000); - Size1 = 0x1000; + /* Reserve memory at 0x00010000: + * Windows NT legacy default executable image base */ + BaseAddress = UlongToPtr(0x00010000); + Size = 0x1000; Status = NtAllocateVirtualMemory(NtCurrentProcess(), - &Mem1, + &BaseAddress, 0, - &Size1, + &Size, MEM_RESERVE, PAGE_READWRITE); ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); + if (NT_SUCCESS(Status)) + { // Unexpected, cleanup. + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + } + + // 0x00400000: Image base. + + /* Reserve memory below 0x00400000 */ + BaseAddress = UlongToPtr(0x00400000 - 0x1000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_READWRITE); + if (NT_SUCCESS(Status)) + { + trace("Below 0x00400000 is available, as on ReactOS and Windows S03\n"); + // 0x003F0000, 64k: Free. + ok_ntstatus(Status, STATUS_SUCCESS); + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + } + else + { + trace("Below 0x00400000 is not available, as on Windows XP\n"); + // 0x003F0000, 4k: Shareable. + // 0x003F1000, 60k: Unusable. + ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); + } + + /* Reserve memory at 0x00400000: + * Windows NT legacy default DLL image base, + * (ReactOS and) Windows 95 new default executable image base */ + BaseAddress = UlongToPtr(0x00400000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_READWRITE); + ok_ntstatus(Status, STATUS_CONFLICTING_ADDRESSES); + if (NT_SUCCESS(Status)) + { // Unexpected, cleanup. + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + } + + // 0x10000000: Free. + + /* Reserve memory below 0x10000000 */ + BaseAddress = UlongToPtr(0x10000000 - 0x1000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_READWRITE); + ok_ntstatus(Status, STATUS_SUCCESS); + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + + /* Reserve memory at 0x10000000: + * Windows new default non-OS DLL image base */ + BaseAddress = UlongToPtr(0x10000000); + Size = 0x1000; + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + &BaseAddress, + 0, + &Size, + MEM_RESERVE, + PAGE_READWRITE); + ok_ntstatus(Status, STATUS_SUCCESS); + Status = NtFreeVirtualMemory(NtCurrentProcess(), &BaseAddress, &Size, MEM_RELEASE); + ok_ntstatus(Status, STATUS_SUCCESS); + +#ifdef _WIN64 + skip("ToDo, 64-bit: Add 0x140000000/Exe and 0x180000000/DLL checks\n"); +#endif +} + +#define RUNS 32 + +START_TEST(NtAllocateVirtualMemory) +{ + PVOID Mem1, Mem2; + SIZE_T Size1, Size2; + ULONG i; + + CheckAlignment(); + CheckAdjacentVADs(); + CheckSomeDefaultAddresses(); Size1 = 32; Mem1 = Allocate(Size1); -- 2.17.1