diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c index 8ff511f7c0e..4efe2f76cf0 100644 --- a/dlls/kernel32/tests/loader.c +++ b/dlls/kernel32/tests/loader.c @@ -225,11 +225,13 @@ static DWORD create_test_dll( const IMAGE_DOS_HEADER *dos_header, UINT dos_size, static void query_image_section( int id, const char *dll_name, const IMAGE_NT_HEADERS *nt_header ) { + SECTION_BASIC_INFORMATION info; SECTION_IMAGE_INFORMATION image; ULONG info_size = 0xdeadbeef; NTSTATUS status; HANDLE file, mapping; ULONG file_size; + LARGE_INTEGER map_size; /* truncated header is not handled correctly in windows <= w2k3 */ BOOL truncated = nt_header->FileHeader.SizeOfOptionalHeader < sizeof(nt_header->OptionalHeader); @@ -288,7 +290,45 @@ static void query_image_section( int id, const char *dll_name, const IMAGE_NT_HE /* image.GpValue */ /* image.ImageFlags */ /* image.ImageContainsCode */ + + map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1); + status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); + ok( !status, "NtQuerySection failed err %x\n", status ); + ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n", + info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); CloseHandle( mapping ); + + map_size.QuadPart = (nt_header->OptionalHeader.SizeOfImage + page_size - 1) & ~(page_size - 1); + status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, + NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); + ok( !status, "%u: NtCreateSection failed err %x\n", id, status ); + status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); + ok( !status, "NtQuerySection failed err %x\n", status ); + ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n", + info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); + CloseHandle( mapping ); + + map_size.QuadPart++; + status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, + NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); + ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %x\n", id, status ); + + SetFilePointerEx( file, map_size, NULL, FILE_BEGIN ); + SetEndOfFile( file ); + status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, + NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); + ok( status == STATUS_SECTION_TOO_BIG, "%u: NtCreateSection failed err %x\n", id, status ); + + map_size.QuadPart = 1; + status = pNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY, + NULL, &map_size, PAGE_READONLY, SEC_IMAGE, file ); + ok( !status, "%u: NtCreateSection failed err %x\n", id, status ); + status = pNtQuerySection( mapping, SectionBasicInformation, &info, sizeof(info), NULL ); + ok( !status, "NtQuerySection failed err %x\n", status ); + ok( info.Size.QuadPart == map_size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n", + info.Size.u.HighPart, info.Size.u.LowPart, map_size.u.HighPart, map_size.u.LowPart ); + CloseHandle( mapping ); + CloseHandle( file ); } @@ -322,7 +362,6 @@ static NTSTATUS map_image_section( const IMAGE_NT_HEADERS *nt_header ) ok( info_size == sizeof(info), "NtQuerySection wrong size %u\n", info_size ); ok( info.Attributes == (SEC_IMAGE | SEC_FILE), "NtQuerySection wrong attr %x\n", info.Attributes ); ok( info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", info.BaseAddress ); - todo_wine ok( info.Size.QuadPart == size.QuadPart, "NtQuerySection wrong size %x%08x / %x%08x\n", info.Size.u.HighPart, info.Size.u.LowPart, size.u.HighPart, size.u.LowPart ); query_image_section( 1000, dll_name, nt_header ); diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 40b1bc90256..26cf09f8ed7 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -992,7 +992,6 @@ static void test_MapViewOfFile(void) ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n", section_info.Attributes ); ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); - todo_wine ok( section_info.Size.QuadPart == 36, "NtQuerySection wrong size %x%08x\n", section_info.Size.u.HighPart, section_info.Size.u.LowPart ); CloseHandle(mapping); @@ -1008,7 +1007,6 @@ static void test_MapViewOfFile(void) ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n", section_info.Attributes ); ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); - todo_wine ok( section_info.Size.QuadPart == 0x3456, "NtQuerySection wrong size %x%08x\n", section_info.Size.u.HighPart, section_info.Size.u.LowPart ); CloseHandle(mapping); @@ -1019,6 +1017,10 @@ static void test_MapViewOfFile(void) todo_wine ok( status == STATUS_SECTION_TOO_BIG, "NtCreateSection failed %x\n", status ); if (!status) CloseHandle( mapping ); + status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, + &map_size, PAGE_READONLY, SEC_IMAGE, file ); + ok( status == STATUS_INVALID_IMAGE_NOT_MZ, "NtCreateSection failed %x\n", status ); + if (!status) CloseHandle( mapping ); map_size.QuadPart = 0x3452; status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, &map_size, PAGE_READONLY, SEC_COMMIT, file ); @@ -1028,9 +1030,17 @@ static void test_MapViewOfFile(void) ok( section_info.Attributes == SEC_FILE, "NtQuerySection wrong attr %08x\n", section_info.Attributes ); ok( section_info.BaseAddress == NULL, "NtQuerySection wrong base %p\n", section_info.BaseAddress ); - todo_wine ok( section_info.Size.QuadPart == 0x3452, "NtQuerySection wrong size %x%08x\n", section_info.Size.u.HighPart, section_info.Size.u.LowPart ); + size = map_size.QuadPart; + status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL, + &size, ViewShare, 0, PAGE_READONLY ); + ok( !status, "NtMapViewOfSection failed err %x\n", status ); + pNtUnmapViewOfSection( GetCurrentProcess(), ptr ); + size = map_size.QuadPart + 1; + status = pNtMapViewOfSection( mapping, GetCurrentProcess(), &ptr, 0, 0, NULL, + &size, ViewShare, 0, PAGE_READONLY ); + ok( status == STATUS_INVALID_VIEW_SIZE, "NtMapViewOfSection failed err %x\n", status ); CloseHandle(mapping); status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, @@ -1055,6 +1065,15 @@ static void test_MapViewOfFile(void) ok( status == STATUS_SECTION_NOT_IMAGE, "NtQuerySection failed err %x\n", status ); CloseHandle(mapping); + SetFilePointer(file, 0, NULL, FILE_BEGIN); + SetEndOfFile(file); + status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, + NULL, PAGE_READONLY, SEC_COMMIT, file ); + ok( status == STATUS_MAPPED_FILE_SIZE_ZERO, "NtCreateSection failed %x\n", status ); + status = pNtCreateSection( &mapping, SECTION_QUERY | SECTION_MAP_READ, NULL, + NULL, PAGE_READONLY, SEC_IMAGE, file ); + ok( status == STATUS_INVALID_FILE_FOR_SECTION, "NtCreateSection failed %x\n", status ); + CloseHandle(file); DeleteFileA(testfile); } diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index fc1349d445e..1312c8bf44f 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -2636,10 +2636,11 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p void *base = wine_server_get_ptr( image_info.base ); if ((ULONG_PTR)base != image_info.base) base = NULL; - size = full_size; - if (size != full_size) /* truncated */ + size = image_info.map_size; + if (size != image_info.map_size) /* truncated */ { - WARN( "Modules larger than 4Gb (%s) not supported\n", wine_dbgstr_longlong(full_size) ); + WARN( "Modules larger than 4Gb (%s) not supported\n", + wine_dbgstr_longlong(image_info.map_size) ); res = STATUS_INVALID_PARAMETER; goto done; } @@ -2668,9 +2669,12 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p if (offset.QuadPart >= full_size) goto done; if (*size_ptr) { - if (*size_ptr > full_size - offset.QuadPart) goto done; - size = ROUND_SIZE( offset.u.LowPart, *size_ptr ); - if (size < *size_ptr) goto done; /* wrap-around */ + size = *size_ptr; + if (size > full_size - offset.QuadPart) + { + res = STATUS_INVALID_VIEW_SIZE; + goto done; + } } else { @@ -2682,6 +2686,7 @@ NTSTATUS WINAPI NtMapViewOfSection( HANDLE handle, HANDLE process, PVOID *addr_p goto done; } } + if (!(size = ROUND_SIZE( 0, size ))) goto done; /* wrap-around */ /* Reserve a properly aligned area */ diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 15fb5a30163..b221570690a 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -682,6 +682,7 @@ typedef struct { client_ptr_t base; client_ptr_t entry_point; + mem_size_t map_size; mem_size_t stack_size; mem_size_t stack_commit; unsigned int zerobits; @@ -6244,6 +6245,6 @@ union generic_reply struct terminate_job_reply terminate_job_reply; }; -#define SERVER_PROTOCOL_VERSION 506 +#define SERVER_PROTOCOL_VERSION 507 #endif /* __WINE_WINE_SERVER_PROTOCOL_H */ diff --git a/server/mapping.c b/server/mapping.c index 71c34371d64..1015a2372e5 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -391,6 +391,7 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s /* load the headers */ + if (!file_size) return STATUS_INVALID_FILE_FOR_SECTION; if (pread( unix_fd, &dos, sizeof(dos), 0 ) != sizeof(dos)) return STATUS_INVALID_IMAGE_NOT_MZ; if (dos.e_magic != IMAGE_DOS_SIGNATURE) return STATUS_INVALID_IMAGE_NOT_MZ; pos = dos.e_lfanew; @@ -438,9 +439,9 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s switch (nt.opt.hdr32.Magic) { case IMAGE_NT_OPTIONAL_HDR32_MAGIC: - mapping->size = ROUND_SIZE( nt.opt.hdr32.SizeOfImage ); mapping->image.base = nt.opt.hdr32.ImageBase; mapping->image.entry_point = nt.opt.hdr32.ImageBase + nt.opt.hdr32.AddressOfEntryPoint; + mapping->image.map_size = ROUND_SIZE( nt.opt.hdr32.SizeOfImage ); mapping->image.stack_size = nt.opt.hdr32.SizeOfStackReserve; mapping->image.stack_commit = nt.opt.hdr32.SizeOfStackCommit; mapping->image.subsystem = nt.opt.hdr32.Subsystem; @@ -452,9 +453,9 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s mapping->image.checksum = nt.opt.hdr32.CheckSum; break; case IMAGE_NT_OPTIONAL_HDR64_MAGIC: - mapping->size = ROUND_SIZE( nt.opt.hdr64.SizeOfImage ); mapping->image.base = nt.opt.hdr64.ImageBase; mapping->image.entry_point = nt.opt.hdr64.ImageBase + nt.opt.hdr64.AddressOfEntryPoint; + mapping->image.map_size = ROUND_SIZE( nt.opt.hdr64.SizeOfImage ); mapping->image.stack_size = nt.opt.hdr64.SizeOfStackReserve; mapping->image.stack_commit = nt.opt.hdr64.SizeOfStackCommit; mapping->image.subsystem = nt.opt.hdr64.Subsystem; @@ -478,7 +479,9 @@ static unsigned int get_image_params( struct mapping *mapping, file_pos_t file_s pos += sizeof(nt.Signature) + sizeof(nt.FileHeader) + nt.FileHeader.SizeOfOptionalHeader; size = sizeof(*sec) * nt.FileHeader.NumberOfSections; - if (pos + size > mapping->size) goto error; + if (!mapping->size) mapping->size = mapping->image.map_size; + else if (mapping->size > mapping->image.map_size) return STATUS_SECTION_TOO_BIG; + if (pos + size > mapping->image.map_size) return STATUS_INVALID_FILE_FOR_SECTION; if (pos + size > mapping->image.header_size) mapping->image.header_size = pos + size; if (!(sec = malloc( size ))) goto error; if (pread( unix_fd, sec, size, pos ) != size) goto error; @@ -513,6 +516,7 @@ static struct object *create_mapping( struct object *root, const struct unicode_ if (get_error() == STATUS_OBJECT_NAME_EXISTS) return &mapping->obj; /* Nothing else to do */ + mapping->size = size; mapping->flags = flags & (SEC_IMAGE | SEC_NOCACHE | SEC_WRITECOMBINE | SEC_LARGE_PAGES); mapping->protect = protect; mapping->fd = NULL; @@ -562,19 +566,19 @@ static struct object *create_mapping( struct object *root, const struct unicode_ set_error( err ); goto error; } - if (!size) + if (!mapping->size) { - if (!(size = st.st_size)) + if (!(mapping->size = st.st_size)) { set_error( STATUS_MAPPED_FILE_SIZE_ZERO ); goto error; } } - else if (st.st_size < size && !grow_file( unix_fd, size )) goto error; + else if (st.st_size < mapping->size && !grow_file( unix_fd, mapping->size )) goto error; } else /* Anonymous mapping (no associated file) */ { - if (!size || (flags & SEC_IMAGE)) + if (!mapping->size || (flags & SEC_IMAGE)) { set_error( STATUS_INVALID_PARAMETER ); goto error; @@ -586,12 +590,12 @@ static struct object *create_mapping( struct object *root, const struct unicode_ mapping->committed->count = 0; mapping->committed->max = 8; } - if ((unix_fd = create_temp_file( size )) == -1) goto error; + mapping->size = (mapping->size + page_mask) & ~((mem_size_t)page_mask); + if ((unix_fd = create_temp_file( mapping->size )) == -1) goto error; if (!(mapping->fd = create_anonymous_fd( &mapping_fd_ops, unix_fd, &mapping->obj, FILE_SYNCHRONOUS_IO_NONALERT ))) goto error; allow_fd_caching( mapping->fd ); } - mapping->size = (size + page_mask) & ~((mem_size_t)page_mask); return &mapping->obj; error: diff --git a/server/protocol.def b/server/protocol.def index cce91d572db..59172122ac6 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -698,6 +698,7 @@ typedef struct { client_ptr_t base; client_ptr_t entry_point; + mem_size_t map_size; mem_size_t stack_size; mem_size_t stack_commit; unsigned int zerobits; diff --git a/server/trace.c b/server/trace.c index cd3c50886bd..9e64b4cc063 100644 --- a/server/trace.c +++ b/server/trace.c @@ -1140,12 +1140,18 @@ static void dump_varargs_pe_image_info( const char *prefix, data_size_t size ) { pe_image_info_t info; + if (!size) + { + fprintf( stderr, "%s{}", prefix ); + return; + } memset( &info, 0, sizeof(info) ); memcpy( &info, cur_data, min( size, sizeof(info) )); fprintf( stderr, "%s{", prefix ); dump_uint64( "base=", &info.base ); dump_uint64( ",entry_point=", &info.entry_point ); + dump_uint64( ",map_size=", &info.map_size ); dump_uint64( ",stack_size=", &info.stack_size ); dump_uint64( ",stack_commit=", &info.stack_commit ); fprintf( stderr, ",zerobits=%08x,subsystem=%08x,subsystem_low=%04x,subsystem_high=%04x,gp=%08x"