[NTDLL_APITEST] Fix/Extend ApiTest NtAllocateVirtualMemory (#207)
authorSerge Gautherie <32623169+SergeGautherie@users.noreply.github.com>
Sat, 17 Mar 2018 16:30:01 +0000 (17:30 +0100)
committerTimo Kreuzer <timo.kreuzer@reactos.org>
Sat, 17 Mar 2018 16:30:01 +0000 (17:30 +0100)
* Fix 1 failure on both WS03 and ReactOS.
* Create CheckSomeDefaultAddresses(), with additional checks.
* Update license header.
* ROSTESTS-297

modules/rostests/apitests/ntdll/NtAllocateVirtualMemory.c

index d1a73cc..aae9405 100644 (file)
@@ -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 <thomas.faber@reactos.org>
+ * PROJECT:     ReactOS API Tests
+ * LICENSE:     GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
+ * PURPOSE:     Test for NtAllocateVirtualMemory
+ * COPYRIGHT:   Copyright 2011 Thomas Faber <thomas.faber@reactos.org>
+ *              Copyright 2013 Timo Kreuzer <timo.kreuzer@reactos.org>
+ *              Copyright 2015 Jérôme Gardou <jerome.gardou@reactos.org>
+ *              Copyright 2018 Serge Gautherie <reactos-git_serge_171003@gautherie.fr>
  */
 
 #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);