ntdll: File positions should be aligned to sector boundaries in PE loader.
This commit is contained in:
parent
11c186fbe7
commit
9fed1205ca
|
@ -404,9 +404,7 @@ START_TEST(loader)
|
||||||
ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
|
ok(info.Type == SEC_IMAGE, "%d: %x != SEC_IMAGE\n", i, info.Type);
|
||||||
|
|
||||||
if (nt_header.OptionalHeader.SectionAlignment >= si.dwPageSize)
|
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");
|
ok(!memcmp((const char *)hlib + section.VirtualAddress + section.PointerToRawData, &nt_header, section.SizeOfRawData), "wrong section data\n");
|
||||||
}
|
|
||||||
else
|
else
|
||||||
ok(!memcmp((const char *)hlib + section.PointerToRawData, section_data, section.SizeOfRawData), "wrong section data\n");
|
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;
|
start = (const char *)hlib + section.VirtualAddress + section.PointerToRawData + section.SizeOfRawData;
|
||||||
size = ALIGN_SIZE((ULONG_PTR)start, si.dwPageSize) - (ULONG_PTR)start;
|
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);
|
ok(memcmp(start, filler, size), "%d: alignment should not be not cleared\n", i);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1051,18 +1051,18 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
||||||
|
|
||||||
for (i = pos = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
|
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)
|
if (!sec->Misc.VirtualSize)
|
||||||
{
|
map_size = ROUND_SIZE( 0, sec->SizeOfRawData );
|
||||||
file_size = sec->SizeOfRawData;
|
|
||||||
map_size = ROUND_SIZE( 0, file_size );
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
map_size = ROUND_SIZE( 0, sec->Misc.VirtualSize );
|
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 */
|
/* a few sanity checks */
|
||||||
end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );
|
end = sec->VirtualAddress + ROUND_SIZE( sec->VirtualAddress, map_size );
|
||||||
|
@ -1115,9 +1115,11 @@ static NTSTATUS map_image( HANDLE hmapping, int fd, char *base, SIZE_T total_siz
|
||||||
/* Note: if the section is not aligned properly map_file_into_view will magically
|
/* 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.
|
* fall back to read(), so we don't need to check anything here.
|
||||||
*/
|
*/
|
||||||
end = sec->PointerToRawData + file_size;
|
end = file_start + file_size;
|
||||||
if (sec->PointerToRawData >= st.st_size || end > st.st_size || end < sec->PointerToRawData ||
|
if (sec->PointerToRawData >= st.st_size ||
|
||||||
map_file_into_view( view, fd, sec->VirtualAddress, file_size, sec->PointerToRawData,
|
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,
|
VPROT_COMMITTED | VPROT_READ | VPROT_WRITECOPY,
|
||||||
removable ) != STATUS_SUCCESS)
|
removable ) != STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
|
|
|
@ -119,25 +119,26 @@ static struct file *get_shared_file( struct mapping *mapping )
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the size of the memory mapping of a given section */
|
/* return the size of the memory mapping and file range of a given section */
|
||||||
static inline unsigned int get_section_map_size( const IMAGE_SECTION_HEADER *sec )
|
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 );
|
static const unsigned int sector_align = 0x1ff;
|
||||||
else return ROUND_SIZE( sec->Misc.VirtualSize );
|
|
||||||
}
|
|
||||||
|
|
||||||
/* return the size of the file mapping of a given section */
|
if (!sec->Misc.VirtualSize) *map_size = ROUND_SIZE( sec->SizeOfRawData );
|
||||||
static inline unsigned int get_section_filemap_size( const IMAGE_SECTION_HEADER *sec )
|
else *map_size = ROUND_SIZE( sec->Misc.VirtualSize );
|
||||||
{
|
|
||||||
if (!sec->Misc.VirtualSize) return sec->SizeOfRawData;
|
*file_start = sec->PointerToRawData & ~sector_align;
|
||||||
else return min( sec->SizeOfRawData, ROUND_SIZE( sec->Misc.VirtualSize ) );
|
*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 */
|
/* allocate and fill the temp file for a shared PE image mapping */
|
||||||
static int build_shared_mapping( struct mapping *mapping, int fd,
|
static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
IMAGE_SECTION_HEADER *sec, unsigned int nb_sec )
|
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;
|
off_t shared_pos, read_pos, write_pos;
|
||||||
char *buffer = NULL;
|
char *buffer = NULL;
|
||||||
int shared_fd;
|
int shared_fd;
|
||||||
|
@ -151,9 +152,9 @@ static int build_shared_mapping( struct mapping *mapping, int fd,
|
||||||
if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
if ((sec[i].Characteristics & IMAGE_SCN_MEM_SHARED) &&
|
||||||
(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE))
|
(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE))
|
||||||
{
|
{
|
||||||
size = get_section_filemap_size( &sec[i] );
|
get_section_sizes( &sec[i], &map_size, &read_pos, &file_size );
|
||||||
if (size > max_size) max_size = size;
|
if (file_size > max_size) max_size = file_size;
|
||||||
total_size += get_section_map_size( &sec[i] );
|
total_size += map_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */
|
if (!(mapping->shared_size = total_size)) return 1; /* nothing to do */
|
||||||
|
@ -175,20 +176,19 @@ 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_SHARED)) continue;
|
||||||
if (!(sec[i].Characteristics & IMAGE_SCN_MEM_WRITE)) 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;
|
write_pos = shared_pos;
|
||||||
shared_pos += get_section_map_size( &sec[i] );
|
shared_pos += map_size;
|
||||||
read_pos = sec[i].PointerToRawData;
|
if (!sec[i].PointerToRawData || !file_size) continue;
|
||||||
size = get_section_filemap_size( &sec[i] );
|
toread = file_size;
|
||||||
if (!read_pos || !size) continue;
|
|
||||||
toread = size;
|
|
||||||
while (toread)
|
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;
|
if (res <= 0) goto error;
|
||||||
toread -= res;
|
toread -= res;
|
||||||
read_pos += 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 );
|
free( buffer );
|
||||||
return 1;
|
return 1;
|
||||||
|
|
Loading…
Reference in New Issue