Alexandre Julliard : ntdll: File positions should be aligned to sector boundaries in PE loader.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Dec 21 10:36:36 CST 2006


Module: wine
Branch: master
Commit: 9fed1205cae7cdb7abacfd3c86523cb22db16ef8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=9fed1205cae7cdb7abacfd3c86523cb22db16ef8

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Thu Dec 21 12:34:44 2006 +0100

ntdll: File positions should be aligned to sector boundaries in PE loader.

---

 dlls/kernel32/tests/loader.c |    4 ----
 dlls/ntdll/virtual.c         |   24 +++++++++++++-----------
 server/mapping.c             |   42 +++++++++++++++++++++---------------------
 3 files changed, 34 insertions(+), 36 deletions(-)

diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index 8811334..4f00e4d 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -404,9 +404,7 @@ START_TEST(loader)
                 ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
 
                 if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
-todo_wine {
                     ok(!memcmp((const char *)hlib + section.VirtualAddress + section.PointerToRawData, &nt_header, section.SizeOfRawData), "wrong section data\n");
-}
                 else
                     ok(!memcmp((const char *)hlib + section.PointerToRawData, section_data, section.SizeOfRawData), "wrong section data\n");
 
@@ -418,9 +416,7 @@ todo_wine {
 
                     start = (const char *)hlib + section.VirtualAddress + section.PointerToRawData + section.SizeOfRawData;
                     size = ALIGN_SIZE((ULONG_PTR)start, si.dwPageSize) - (ULONG_PTR)start;
-todo_wine {
                     ok(memcmp(start, filler, size), "%d: alignment should not be not cleared\n", i);
-}
                 }
             }
 
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 152af7b..fe33566 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1051,18 +1051,18 @@ static NTSTATUS map_image( HANDLE hmappi
 
     for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
     {
-        SIZE_T map_size, file_size, end;
+        static const SIZE_T sector_align = 0x1ff;
+        SIZE_T map_size, file_start, file_size, end;
 
         if (!sec->Misc.VirtualSize)
-        {
-            file_size = sec->SizeOfRawData;
-            map_size  = ROUND_SIZE( 0, file_size );
-        }
+            map_size = ROUND_SIZE( 0, sec->SizeOfRawData );
         else
-        {
             map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
-            file_size = min( sec->SizeOfRawData, map_size );
-        }
+
+        /* file positions are rounded to sector boundaries regardless of OptionalHeader.FileAlignment */
+        file_start = sec->PointerToRawData & ~sector_align;
+        file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;
+        if (file_size > map_size) file_size = map_size;
 
         /* a few sanity checks */
         end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );
@@ -1115,9 +1115,11 @@ static NTSTATUS map_image( HANDLE hmappi
         /* 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.
          */
-        end = sec->PointerToRawData + file_size;
-        if (sec->PointerToRawData >= st.st_size || end > st.st_size || end < sec->PointerToRawData ||
-            map_file_into_view( view, fd, sec->VirtualAddress, file_size, sec->PointerToRawData,
+        end = file_start + file_size;
+        if (sec->PointerToRawData >= st.st_size ||
+            end > ((st.st_size + sector_align) & ~sector_align) ||
+            end < file_start ||
+            map_file_into_view( view, fd, sec->VirtualAddress, file_size, file_start,
                                 VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
                                 removable ) != STATUS_SUCCESS)
         {
diff --git a/server/mapping.c b/server/mapping.c
index 052ea41..c7eb075 100644
--- a/server/mapping.c
+++ b/server/mapping.c
@@ -119,25 +119,26 @@ static struct file *get_shared_file( str
     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 )
+/* return the size of the memory mapping and file range of a given section */
+static inline void get_section_sizes( const IMAGE_SECTION_HEADER *sec, size_t *map_size,
+                                      off_t *file_start, size_t *file_size )
 {
-    if (!sec->Misc.VirtualSize) return ROUND_SIZE( sec->SizeOfRawData );
-    else return ROUND_SIZE( sec->Misc.VirtualSize );
-}
+    static const unsigned int sector_align = 0x1ff;
 
-/* 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 ) );
+    if (!sec->Misc.VirtualSize) *map_size = ROUND_SIZE( sec->SizeOfRawData );
+    else *map_size = ROUND_SIZE( sec->Misc.VirtualSize );
+
+    *file_start = sec->PointerToRawData & ~sector_align;
+    *file_size = (sec->SizeOfRawData + (sec->PointerToRawData & sector_align) + sector_align) & ~sector_align;
+    if (*file_size > *map_size) *file_size = *map_size;
 }
 
 /* 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, size, max_size, total_size;
+    unsigned int i;
+    size_t file_size, map_size, max_size, total_size;
     off_t shared_pos, read_pos, write_pos;
     char *buffer = NULL;
     int shared_fd;
@@ -151,9 +152,9 @@ static int build_shared_mapping( struct
         if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) &&
             (sec[i].Characteristics & IMAGE_SCN_MEM_WRITE))
         {
-            size = get_section_filemap_size( &sec[i] );
-            if (size > max_size) max_size = size;
-            total_size += get_section_map_size( &sec[i] );
+            get_section_sizes( &sec[i], &map_size, &read_pos, &file_size );
+            if (file_size > max_size) max_size = file_size;
+            total_size += map_size;
         }
     }
     if (!(mapping->shared_size = total_size)) return 1;  /* nothing to do */
@@ -175,20 +176,19 @@ static int build_shared_mapping( struct
     {
         if (!(sec[i].Characteristics & IMAGE_SCN_MEM_SHARED)) continue;
         if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) continue;
+        get_section_sizes( &sec[i], &map_size, &read_pos, &file_size );
         write_pos = shared_pos;
-        shared_pos += get_section_map_size( &sec[i] );
-        read_pos = sec[i].PointerToRawData;
-        size = get_section_filemap_size( &sec[i] );
-        if (!read_pos || !size) continue;
-        toread = size;
+        shared_pos += map_size;
+        if (!sec[i].PointerToRawData || !file_size) continue;
+        toread = file_size;
         while (toread)
         {
-            long res = pread( fd, buffer + sec[i].SizeOfRawData - toread, toread, read_pos );
+            long res = pread( fd, buffer + file_size - toread, toread, read_pos );
             if (res <= 0) goto error;
             toread -= res;
             read_pos += res;
         }
-        if (pwrite( shared_fd, buffer, size, write_pos ) != size) goto error;
+        if (pwrite( shared_fd, buffer, file_size, write_pos ) != file_size) goto error;
     }
     free( buffer );
     return 1;




More information about the wine-cvs mailing list