From 4ebd2fc0ffb8f51e2d64f3e6df264b2d2b2cd4bf Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 15 Aug 2005 14:50:06 +0000 Subject: [PATCH] Better handling of conflicting section information between SizeOfRawData and VirtualSize. --- dlls/ntdll/virtual.c | 57 +++++++++++++++++++++++++------------------- server/mapping.c | 30 ++++++++++++++++------- 2 files changed, 54 insertions(+), 33 deletions(-) diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c index 9fb0d38a3c4..cac0cc72db9 100644 --- a/dlls/ntdll/virtual.c +++ b/dlls/ntdll/virtual.c @@ -920,27 +920,36 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++) { - SIZE_T size; + SIZE_T map_size, file_size, end; - /* a few sanity checks */ - size = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, sec->Misc.VirtualSize ); - if (sec->VirtualAddress > total_size || size > total_size || size < sec->VirtualAddress) + if (!sec->Misc.VirtualSize) { - ERR_(module)( "Section %.8s too large (%lx+%lx/%lx)\n", - sec->Name, sec->VirtualAddress, sec->Misc.VirtualSize, total_size ); - goto error; + file_size = sec->SizeOfRawData; + map_size = ROUND_SIZE( 0, file_size ); + } + else + { + map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize ); + file_size = min( sec->SizeOfRawData, map_size ); } - size = ROUND_SIZE( 0, sec->Misc.VirtualSize ); + /* a few sanity checks */ + end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size ); + if (sec->VirtualAddress > total_size || end > total_size || end < sec->VirtualAddress) + { + ERR_(module)( "Section %.8s too large (%lx+%lx/%lx)\n", + sec->Name, sec->VirtualAddress, map_size, total_size ); + goto error; + } if ((sec->Characteristics & IMAGE_SCN_MEM_SHARED) && (sec->Characteristics & IMAGE_SCN_MEM_WRITE)) { TRACE_(module)( "mapping shared section %.8s at %p off %lx (%x) size %lx (%lx) flags %lx\n", - sec->Name, ptr + sec->VirtualAddress, - sec->PointerToRawData, (int)pos, sec->SizeOfRawData, - size, sec->Characteristics ); - if (map_file_into_view( view, shared_fd, sec->VirtualAddress, size, pos, + sec->Name, ptr + sec->VirtualAddress, + sec->PointerToRawData, (int)pos, file_size, map_size, + sec->Characteristics ); + if (map_file_into_view( view, shared_fd, sec->VirtualAddress, map_size, pos, VPROT_COMMITTED | VPROT_READ | PROT_WRITE, FALSE ) != STATUS_SUCCESS) { @@ -950,33 +959,32 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz /* check if the import directory falls inside this section */ if (imports && imports->VirtualAddress >= sec->VirtualAddress && - imports->VirtualAddress < sec->VirtualAddress + size) + imports->VirtualAddress < sec->VirtualAddress + map_size) { UINT_PTR base = imports->VirtualAddress & ~page_mask; UINT_PTR end = base + ROUND_SIZE( imports->VirtualAddress, imports->Size ); - if (end > sec->VirtualAddress + size) end = sec->VirtualAddress + size; + if (end > sec->VirtualAddress + map_size) end = sec->VirtualAddress + map_size; if (end > base) map_file_into_view( view, shared_fd, base, end - base, pos + (base - sec->VirtualAddress), VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY, FALSE ); } - pos += size; + pos += map_size; continue; } TRACE_(module)( "mapping section %.8s at %p off %lx size %lx virt %lx flags %lx\n", sec->Name, ptr + sec->VirtualAddress, sec->PointerToRawData, sec->SizeOfRawData, - size, sec->Characteristics ); + sec->Misc.VirtualSize, sec->Characteristics ); - if (!sec->PointerToRawData || !sec->SizeOfRawData) continue; - if (sec->SizeOfRawData < size) size = sec->SizeOfRawData; + if (!sec->PointerToRawData || !file_size) continue; /* Note: if the section is not aligned properly map_file_into_view will magically * fall back to read(), so we don't need to check anything here. */ - if (map_file_into_view( view, fd, sec->VirtualAddress, size, sec->PointerToRawData, + if (map_file_into_view( view, fd, sec->VirtualAddress, file_size, sec->PointerToRawData, VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY, removable ) != STATUS_SUCCESS) { @@ -984,15 +992,14 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz goto error; } - if ((sec->SizeOfRawData < sec->Misc.VirtualSize) && (sec->SizeOfRawData & page_mask)) + if (file_size & page_mask) { - DWORD end = ROUND_SIZE( 0, sec->SizeOfRawData ); - if (end > sec->Misc.VirtualSize) end = sec->Misc.VirtualSize; + end = ROUND_SIZE( 0, file_size ); + if (end > map_size) end = map_size; TRACE_(module)("clearing %p - %p\n", - ptr + sec->VirtualAddress + sec->SizeOfRawData, + ptr + sec->VirtualAddress + file_size, ptr + sec->VirtualAddress + end ); - memset( ptr + sec->VirtualAddress + sec->SizeOfRawData, 0, - end - sec->SizeOfRawData ); + memset( ptr + sec->VirtualAddress + file_size, 0, end - file_size ); } } diff --git a/server/mapping.c b/server/mapping.c index 5826fef839d..81e4806c672 100644 --- a/server/mapping.c +++ b/server/mapping.c @@ -116,11 +116,25 @@ static struct file *get_shared_file( struct mapping *mapping ) return NULL; } +/* return the size of the memory mapping of a given section */ +static inline unsigned int get_section_map_size( const IMAGE_SECTION_HEADER *sec ) +{ + if (!sec->Misc.VirtualSize) return ROUND_SIZE( sec->SizeOfRawData ); + else return ROUND_SIZE( sec->Misc.VirtualSize ); +} + +/* return the size of the file mapping of a given section */ +static inline unsigned int get_section_filemap_size( const IMAGE_SECTION_HEADER *sec ) +{ + if (!sec->Misc.VirtualSize) return sec->SizeOfRawData; + else return min( sec->SizeOfRawData, ROUND_SIZE( sec->Misc.VirtualSize ) ); +} + /* allocate and fill the temp file for a shared PE image mapping */ static int build_shared_mapping( struct mapping *mapping, int fd, IMAGE_SECTION_HEADER *sec, unsigned int nb_sec ) { - unsigned int i, max_size, total_size; + unsigned int i, size, max_size, total_size; off_t shared_pos, read_pos, write_pos; char *buffer = NULL; int shared_fd; @@ -134,9 +148,9 @@ static int build_shared_mapping( struct mapping *mapping, int fd, if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) && (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { - unsigned int size = ROUND_SIZE( sec[i].Misc.VirtualSize ); + size = get_section_filemap_size( &sec[i] ); if (size > max_size) max_size = size; - total_size += size; + total_size += get_section_map_size( &sec[i] ); } } if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */ @@ -159,10 +173,11 @@ static int build_shared_mapping( struct mapping *mapping, int fd, if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue; if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue; write_pos = shared_pos; - shared_pos += ROUND_SIZE( sec[i].Misc.VirtualSize ); - if (!sec[i].PointerToRawData || !sec[i].SizeOfRawData) continue; + shared_pos += get_section_map_size( &sec[i] ); read_pos = sec[i].PointerToRawData; - toread = sec[i].SizeOfRawData; + size = get_section_filemap_size( &sec[i] ); + if (!read_pos || !size) continue; + toread = size; while (toread) { long res = pread( fd, buffer + sec[i].SizeOfRawData - toread, toread, read_pos ); @@ -170,8 +185,7 @@ static int build_shared_mapping( struct mapping *mapping, int fd, toread -= res; read_pos += res; } - if (pwrite( shared_fd, buffer, sec[i].SizeOfRawData, write_pos ) != sec[i].SizeOfRawData) - goto error; + if (pwrite( shared_fd, buffer, size, write_pos ) != size) goto error; } free( buffer ); return 1;