Module: wine Branch: master Commit: 7d2a7b94aad8a776a2ee3031a18bb3b53d5925cd URL: https://source.winehq.org/git/wine.git/?a=commit;h=7d2a7b94aad8a776a2ee3031a...
Author: Alexandre Julliard julliard@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@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;