[Bug 52119] New: EndUpdateResource calculates field "SizeofImage" wrong
WineHQ Bugzilla
wine-bugs at winehq.org
Fri Nov 26 18:29:59 CST 2021
https://bugs.winehq.org/show_bug.cgi?id=52119
Bug ID: 52119
Summary: EndUpdateResource calculates field "SizeofImage" wrong
Product: Wine
Version: 6.22
Hardware: x86-64
OS: Linux
Status: UNCONFIRMED
Severity: normal
Priority: P2
Component: kernel32
Assignee: wine-bugs at winehq.org
Reporter: info at daniel-marschall.de
Distribution: ---
The function `EndUpdateResource` will calculate the PE field "SizeOfImage" like
this:
For 64 bit:
nt64->OptionalHeader.SizeOfImage += rva_delta;
For 32 bit:
nt->OptionalHeader.SizeOfImage += rva_delta;
But this is wrong. It does not follow the specification of Microsoft, and
therefore, some combinations of SizeofImage values and Windows versions will
cause the Operating System to deny loading the image.
The correct implementation is described here:
https://stackoverflow.com/questions/39022853/how-is-sizeofimage-in-the-pe-optional-header-computed
Correct is following code (to be added to `write_raw_resources`):
For 64 bit:
lastsec = get_last_section(write_map->base, mapping_size);
pEndOfLastSection = lastsec->VirtualAddress +
lastsec->Misc.VirtualSize + nt64->OptionalHeader.ImageBase;
//NOTE: we are rounding to memory section alignment, not file
pEndOfLastSectionMem =
peRoundUpToAlignment64(nt64->OptionalHeader.SectionAlignment,
pEndOfLastSection);
uCalcSizeOfFile = pEndOfLastSectionMem -
nt64->OptionalHeader.ImageBase;
nt64->OptionalHeader.SizeOfImage = (DWORD)uCalcSizeOfFile;
For 32 bit:
//nt->OptionalHeader.SizeOfImage += rva_delta;
// Fix by Daniel Marschall: Added this calculation of
"SizeOfImage".
// With the original implementation, Windows won't load some
images!
//
https://stackoverflow.com/questions/39022853/how-is-sizeofimage-in-the-pe-optional-header-computed
lastsec = get_last_section(write_map->base, mapping_size);
pEndOfLastSection = lastsec->VirtualAddress +
lastsec->Misc.VirtualSize + nt->OptionalHeader.ImageBase;
//NOTE: we are rounding to memory section alignment, not file
pEndOfLastSectionMem =
peRoundUpToAlignment(nt->OptionalHeader.SectionAlignment, pEndOfLastSection);
uCalcSizeOfFile = pEndOfLastSectionMem -
nt->OptionalHeader.ImageBase;
nt->OptionalHeader.SizeOfImage = uCalcSizeOfFile;
And the required functions:
//
// peRoundUpToAlignment() - rounds dwValue up to nearest dwAlign
//
DWORD peRoundUpToAlignment(DWORD dwAlign, DWORD dwVal)
{
// Fix by Fix by Daniel Marschall: Added this function, based on
//
https://stackoverflow.com/questions/39022853/how-is-sizeofimage-in-the-pe-optional-header-computed
if (dwAlign)
{
//do the rounding with bitwise operations...
//create bit mask of bits to keep
// e.g. if section alignment is 0x1000
1000000000000
// we want the following bitmask
11111111111111111111000000000000
DWORD dwMask = ~(dwAlign - 1);
//round up by adding full alignment (dwAlign-1 since if already aligned
we don't want anything to change),
// then mask off any lower bits
dwVal = (dwVal + dwAlign - 1) & dwMask;
}
return(dwVal);
}
ULONGLONG peRoundUpToAlignment64(ULONGLONG dwAlign, ULONGLONG dwVal)
{
// Fix by Fix by Daniel Marschall: Added this function, based on
//
https://stackoverflow.com/questions/39022853/how-is-sizeofimage-in-the-pe-optional-header-computed
if (dwAlign)
{
//do the rounding with bitwise operations...
//create bit mask of bits to keep
// e.g. if section alignment is 0x1000
1000000000000
// we want the following bitmask
11111111111111111111000000000000
ULONGLONG dwMask = ~(dwAlign - 1);
//round up by adding full alignment (dwAlign-1 since if already aligned
we don't want anything to change),
// then mask off any lower bits
dwVal = (dwVal + dwAlign - 1) & dwMask;
}
return(dwVal);
}
static IMAGE_SECTION_HEADER* get_last_section(void* base, DWORD mapping_size)
{
// Fix by Fix by Daniel Marschall: Added this function which is required by
the "SizeOfImage" field calculation
IMAGE_SECTION_HEADER* sec;
IMAGE_NT_HEADERS* nt;
DWORD num_sections = 0;
nt = get_nt_header(base, mapping_size);
if (!nt)
return NULL;
sec = get_section_header(base, mapping_size, &num_sections);
if (!sec)
return NULL;
/* find the resources section */
return &sec[num_sections - 1];
}
--
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.
More information about the wine-bugs
mailing list