Alexandre Julliard : ntdll: Fix handling of zero size with MEM_DECOMMIT.
Alexandre Julliard
julliard at winehq.org
Fri Nov 19 15:45:31 CST 2021
Module: wine
Branch: master
Commit: 7d2a7b94aad8a776a2ee3031a18bb3b53d5925cd
URL: https://source.winehq.org/git/wine.git/?a=commit;h=7d2a7b94aad8a776a2ee3031a18bb3b53d5925cd
Author: Alexandre Julliard <julliard at winehq.org>
Date: Fri Nov 19 11:04:30 2021 +0100
ntdll: Fix handling of zero size with MEM_DECOMMIT.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52023
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/tests/virtual.c | 43 +++++++++++++++++++++++++++++++++++++++++++
dlls/ntdll/unix/virtual.c | 17 ++++++++++-------
2 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index 5f155b1a147..53adee5896d 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -219,6 +219,49 @@ static void test_NtAllocateVirtualMemory(void)
status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE);
ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory failed\n");
+ /* NtFreeVirtualMemory tests */
+
+ size = 0x10000;
+ addr1 = NULL;
+ status = NtAllocateVirtualMemory(NtCurrentProcess(), &addr1, 0, &size,
+ MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
+ ok(status == STATUS_SUCCESS, "NtAllocateVirtualMemory returned %08x\n", status);
+
+ size = 2;
+ addr2 = (char *)addr1 + 0x1fff;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_DECOMMIT);
+ ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory failed %x\n", status);
+ ok( size == 0x2000, "wrong size %lx\n", size );
+ ok( addr2 == (char *)addr1 + 0x1000, "wrong addr %p\n", addr2 );
+
+ size = 0;
+ addr2 = (char *)addr1 + 0x1001;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_DECOMMIT);
+ ok(status == STATUS_FREE_VM_NOT_AT_BASE, "NtFreeVirtualMemory failed %x\n", status);
+ ok( size == 0, "wrong size %lx\n", size );
+ ok( addr2 == (char *)addr1 + 0x1001, "wrong addr %p\n", addr2 );
+
+ size = 0;
+ addr2 = (char *)addr1 + 0xffe;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_DECOMMIT);
+ ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory failed %x\n", status);
+ ok( size == 0, "wrong size %lx\n", size );
+ ok( addr2 == addr1, "wrong addr %p\n", addr2 );
+
+ size = 0;
+ addr2 = (char *)addr1 + 0x1001;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE);
+ ok(status == STATUS_FREE_VM_NOT_AT_BASE, "NtFreeVirtualMemory failed %x\n", status);
+ ok( size == 0, "wrong size %lx\n", size );
+ ok( addr2 == (char *)addr1 + 0x1001, "wrong addr %p\n", addr2 );
+
+ size = 0;
+ addr2 = (char *)addr1 + 0xfff;
+ status = NtFreeVirtualMemory(NtCurrentProcess(), &addr2, &size, MEM_RELEASE);
+ ok(status == STATUS_SUCCESS, "NtFreeVirtualMemory failed %x\n", status);
+ ok( size == 0x10000, "wrong size %lx\n", size );
+ ok( addr2 == addr1, "wrong addr %p\n", addr2 );
+
if (!pNtAllocateVirtualMemoryEx)
{
win_skip("NtAllocateVirtualMemoryEx() is missing\n");
diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c
index f62ca1f5f01..5873a3e2335 100644
--- a/dlls/ntdll/unix/virtual.c
+++ b/dlls/ntdll/unix/virtual.c
@@ -2121,13 +2121,14 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, BYTE *vpro
/***********************************************************************
- * decommit_view
+ * decommit_pages
*
* Decommit some pages of a given view.
* virtual_mutex must be held by caller.
*/
static NTSTATUS decommit_pages( struct file_view *view, size_t start, size_t size )
{
+ if (!size) size = view->size;
if (anon_mmap_fixed( (char *)view->base + start, size, PROT_NONE, 0 ) != MAP_FAILED)
{
set_page_vprot_bits( (char *)view->base + start, size, 0, VPROT_COMMITTED );
@@ -3966,7 +3967,7 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
/* Fix the parameters */
- size = ROUND_SIZE( addr, size );
+ if (size) size = ROUND_SIZE( addr, size );
base = ROUND_ADDR( addr, page_mask );
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
@@ -3975,7 +3976,7 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
if (!base)
{
/* address 1 is magic to mean release reserved space */
- if (addr == (void *)1 && !*size_ptr && type == MEM_RELEASE) virtual_release_address_space();
+ if (addr == (void *)1 && !size && type == MEM_RELEASE) virtual_release_address_space();
else status = STATUS_INVALID_PARAMETER;
}
else if (!(view = find_view( base, size )) || !is_view_valloc( view ))
@@ -3986,17 +3987,19 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si
{
/* Free the pages */
- if (size || (base != view->base)) status = STATUS_INVALID_PARAMETER;
+ if (size) status = STATUS_INVALID_PARAMETER;
+ else if (base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE;
else
{
- delete_view( view );
*addr_ptr = base;
- *size_ptr = size;
+ *size_ptr = view->size;
+ delete_view( view );
}
}
else if (type == MEM_DECOMMIT)
{
- status = decommit_pages( view, base - (char *)view->base, size );
+ if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE;
+ else status = decommit_pages( view, base - (char *)view->base, size );
if (status == STATUS_SUCCESS)
{
*addr_ptr = base;
More information about the wine-cvs
mailing list