Signed-off-by: Brendan Shanks bshanks@codeweavers.com ---
The zero_bits mask test always passes on 32-bit (the pointer is either truncated, or version.dll is itself 32-bit).
dlls/ntdll/tests/virtual.c | 41 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index 30a97ba9d94..cd374cf2ea4 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -37,6 +37,8 @@ static ULONG64 (WINAPI *pRtlGetEnabledExtendedFeatures)(ULONG64); static NTSTATUS (WINAPI *pRtlFreeUserStack)(void *); static void * (WINAPI *pRtlFindExportedRoutineByName)(HMODULE,const char*); static BOOL (WINAPI *pIsWow64Process)(HANDLE, PBOOL); +static BOOL (WINAPI *pWow64DisableWow64FsRedirection)(PVOID*); +static BOOL (WINAPI *pWow64RevertWow64FsRedirection)(PVOID); static NTSTATUS (WINAPI *pNtAllocateVirtualMemoryEx)(HANDLE, PVOID *, SIZE_T *, ULONG, ULONG, MEM_EXTENDED_PARAMETER *, ULONG); static const BOOL is_win64 = sizeof(void*) != sizeof(int); @@ -904,6 +906,43 @@ static void test_NtMapViewOfSection(void) CloseHandle(file); DeleteFileA(testfile);
+ /* test zero_bits > 31 with a 64-bit DLL if possible */ + if (is_wow64) + pWow64DisableWow64FsRedirection(&ptr2); + + file = CreateFileA("c:\windows\system32\version.dll", GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "Failed to open version.dll\n"); + + if (is_wow64) + pWow64RevertWow64FsRedirection(ptr2); + + mapping = CreateFileMappingA(file, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, NULL); + ok(mapping != 0, "CreateFileMapping failed\n"); + + ptr = NULL; + size = 0; + offset.QuadPart = 0; + zero_bits = 0x7fffffff; + status = NtMapViewOfSection(mapping, process, &ptr, zero_bits, 0, &offset, &size, 1, 0, PAGE_READONLY); + + if (!is_win64 && !is_wow64) + { + ok(status == STATUS_INVALID_PARAMETER_4, "NtMapViewOfSection returned %08lx\n", status); + } + else + { + ok(status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE, "NtMapViewOfSection returned %08lx\n", status); + ok(!((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr); + todo_wine + ok(((UINT_PTR)ptr & ~get_zero_bits_mask(zero_bits)) == 0, "NtMapViewOfSection returned address %p\n", ptr); + + status = NtUnmapViewOfSection(process, ptr); + ok(status == STATUS_SUCCESS, "NtUnmapViewOfSection returned %08lx\n", status); + } + + NtClose(mapping); + CloseHandle(file); + TerminateProcess(process, 0); CloseHandle(process); } @@ -1152,6 +1191,8 @@ START_TEST(virtual)
mod = GetModuleHandleA("kernel32.dll"); pIsWow64Process = (void *)GetProcAddress(mod, "IsWow64Process"); + pWow64DisableWow64FsRedirection = (void *)GetProcAddress(mod, "Wow64DisableWow64FsRedirection"); + pWow64RevertWow64FsRedirection = (void *)GetProcAddress(mod, "Wow64RevertWow64FsRedirection"); pGetEnabledXStateFeatures = (void *)GetProcAddress(mod, "GetEnabledXStateFeatures"); mod = GetModuleHandleA("ntdll.dll"); pRtlCreateUserStack = (void *)GetProcAddress(mod, "RtlCreateUserStack");
Signed-off-by: Brendan Shanks bshanks@codeweavers.com ---
v2: return CONFLICTING_ADDRESSES for map_view().
The map_view() change fixes native DLLs, and virtual_map_section() for builtin DLLs. I wasn't sure how to test a native DLL.
This showed up under Wow64 when running the 64-bit Notepad++ installer (a 32-bit EXE), which runs 32-bit regsvr32 to register a 64-bit DLL. regsvr32 calls LoadLibraryExW() with LOAD_LIBRARY_AS_IMAGE_RESOURCE, which was returning a truncated pointer to the DLLs base address. Accessing this then crashed.
dlls/ntdll/tests/virtual.c | 1 - dlls/ntdll/unix/virtual.c | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c index cd374cf2ea4..0b1b7921d8a 100644 --- a/dlls/ntdll/tests/virtual.c +++ b/dlls/ntdll/tests/virtual.c @@ -933,7 +933,6 @@ static void test_NtMapViewOfSection(void) { ok(status == STATUS_SUCCESS || status == STATUS_IMAGE_NOT_AT_BASE, "NtMapViewOfSection returned %08lx\n", status); ok(!((ULONG_PTR)ptr & 0xffff), "returned memory %p is not aligned to 64k\n", ptr); - todo_wine ok(((UINT_PTR)ptr & ~get_zero_bits_mask(zero_bits)) == 0, "NtMapViewOfSection returned address %p\n", ptr);
status = NtUnmapViewOfSection(process, ptr); diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 94b300c5057..bfa51ba786b 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -1904,6 +1904,8 @@ static NTSTATUS map_view( struct file_view **view_ret, void *base, size_t size, { if (is_beyond_limit( base, size, address_space_limit )) return STATUS_WORKING_SET_LIMIT_RANGE; + if (is_beyond_limit( base, size, (void*)get_zero_bits_mask( zero_bits ) )) + return STATUS_CONFLICTING_ADDRESSES; status = map_fixed_area( base, size, vprot ); if (status != STATUS_SUCCESS) return status; ptr = base; @@ -2540,7 +2542,8 @@ static NTSTATUS virtual_map_section( HANDLE handle, PVOID *addr_ptr, ULONG_PTR z filename = (WCHAR *)(image_info + 1); /* check if we can replace that mapping with the builtin */ res = load_builtin( image_info, filename, addr_ptr, size_ptr ); - if (res == STATUS_IMAGE_ALREADY_LOADED) + if (res == STATUS_IMAGE_ALREADY_LOADED || + is_beyond_limit( (void *)image_info->base, image_info->map_size, (void *)get_zero_bits_mask( zero_bits ) )) res = virtual_map_image( handle, access, addr_ptr, size_ptr, zero_bits, shared_file, alloc_type, image_info, filename, FALSE ); if (shared_file) NtClose( shared_file );
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=113625
Your paranoid android.
=== debian11 (32 bit WoW report) ===
ntdll: virtual.c:937: Test succeeded inside todo block: NtMapViewOfSection returned address 63280000
=== debian11 (64 bit WoW report) ===
ntdll: virtual.c:937: Test succeeded inside todo block: NtMapViewOfSection returned address 0000000063280000