Module: wine Branch: master Commit: e90b2bb9502d60c869c0596c910b41b85b2cd8f2 URL: https://gitlab.winehq.org/wine/wine/-/commit/e90b2bb9502d60c869c0596c910b41b...
Author: Paul Gofman pgofman@codeweavers.com Date: Fri Nov 11 18:12:47 2022 -0600
ntdll: Fix size validation in NtFreeVirtualMemory().
---
dlls/ntdll/tests/virtual.c | 16 ++++++++-------- dlls/ntdll/unix/virtual.c | 26 ++++++++++++++++++-------- 2 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index cc551800811..555dbb5b4ff 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -1857,12 +1857,12 @@ static void test_NtFreeVirtualMemory(void)
size = 0x11000; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr1, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status); + ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status);
addr = (char *)addr1 + 0x1001; size = 0xffff; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status); + ok(status == STATUS_UNABLE_TO_FREE_VM, "Unexpected status %08lx.\n", status); ok(size == 0xffff, "Unexpected size %p.\n", (void *)size); ok(addr == (char *)addr1 + 0x1001, "Got addr %p, addr1 %p.\n", addr, addr1);
@@ -1872,16 +1872,16 @@ static void test_NtFreeVirtualMemory(void) todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); *(volatile char *)addr1 = 1; *((volatile char *)addr1 + 0x2000) = 1; - todo_wine ok(size == 0x1000, "Unexpected size %p.\n", (void *)size); - todo_wine ok(addr == (char *)addr1 + 0x1000, "Got addr %p, addr1 %p.\n", addr, addr1); + ok(size == 0x1000, "Unexpected size %p.\n", (void *)size); + ok(addr == (char *)addr1 + 0x1000, "Got addr %p, addr1 %p.\n", addr, addr1);
size = 0xfff; addr = (char *)addr1 + 1; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); todo_wine ok(status == STATUS_SUCCESS, "Unexpected status %08lx.\n", status); *((volatile char *)addr1 + 0x2000) = 1; - todo_wine ok(size == 0x1000, "Unexpected size %p.\n", (void *)size); - todo_wine ok(addr == addr1, "Got addr %p, addr1 %p.\n", addr, addr1); + ok(size == 0x1000, "Unexpected size %p.\n", (void *)size); + ok(addr == addr1, "Got addr %p, addr1 %p.\n", addr, addr1);
size = 0x1000; addr = addr1; @@ -1901,12 +1901,12 @@ static void test_NtFreeVirtualMemory(void) size = 0; addr = (char *)addr1 + 0x1000; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_RELEASE); - todo_wine ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status); + ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
size = 0x1000; addr = (char *)addr1 + 0x1000; status = NtFreeVirtualMemory(NtCurrentProcess(), &addr, &size, MEM_DECOMMIT); - todo_wine ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status); + ok(status == STATUS_MEMORY_NOT_ALLOCATED, "Unexpected status %08lx.\n", status);
size = 0; addr = (char *)addr1 + 0x2000; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index c7d2b0dcfde..9d6c7281ff7 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -4204,26 +4204,36 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si 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 )) - { - status = STATUS_INVALID_PARAMETER; - } + else if (!(view = find_view( base, 0 ))) status = STATUS_MEMORY_NOT_ALLOCATED; + else if (!is_view_valloc( view )) status = STATUS_INVALID_PARAMETER; else if (type == MEM_RELEASE) { /* Free the pages */
- if (size) status = STATUS_INVALID_PARAMETER; - else if (base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE; + if (size && (char *)view->base + view->size - base < size) status = STATUS_UNABLE_TO_FREE_VM; + else if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE; else { + if (!size) size = view->size; + + if (size == view->size) + { + assert( base == view->base ); + delete_view( view ); + } + else + { + FIXME( "Parial view release is not supported.\n" ); + status = STATUS_INVALID_PARAMETER; + } *addr_ptr = base; - *size_ptr = view->size; - delete_view( view ); + *size_ptr = size; } } else if (type == MEM_DECOMMIT) { if (!size && base != view->base) status = STATUS_FREE_VM_NOT_AT_BASE; + else if (base - (char *)view->base + size > view->size) status = STATUS_UNABLE_TO_FREE_VM; else status = decommit_pages( view, base - (char *)view->base, size ); if (status == STATUS_SUCCESS) {