ntdll: Fix size validation in NtFreeVirtualMemory().

This commit is contained in:
Paul Gofman 2022-11-11 18:12:47 -06:00 committed by Alexandre Julliard
parent d8fc23d86e
commit e90b2bb950
2 changed files with 26 additions and 16 deletions

View file

@ -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;

View file

@ -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)
{