Thanks for your detailed bug report.
I tried to reproduce the bug via the Disco Dingo Ubuntu/arm64 cloud
image running inside the QEMU emulator [1]. I did not succeed in
triggering the bug with this setup.
I concluded from your debug output that the icon group boundary is not
aligned to the nearest multiple of a double word.
The size of the icon group is calculated as the following:
size_t group_size = sizeof(IconGroupHeader) // header
+ order.size() * SIZEOF_RSRC_ICON_GROUP_ENTRY; // entries
sizeof(IconGroupHeader) = 6
SIZEOF_RSRC_ICON_GROUP_ENTRY = 14
group_size is a multiple of a double word for uneven numbers of
order.size() but not if order.size() is an even number.
For illustration group_size for the order.size() values of 1 and 2:
group_size = 6 + 1 * 14 = 20 (double word aligned)
group_size = 6 + 2 * 14 = 34 (not double word aligned)
Therefore I expect something like the attached patch
(fix-icongroup-alignment.patch) would be necessary. I need to verify
with the
Microsoft Portable Executable and Common Object File Format
Specification [2] and upstream.
[1] https://wiki.ubuntu.com/ARM64/QEMU
[2] http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx
Align icon group boundary to the nearest multiple of a double word.
--- a/Source/icon.cpp
+++ b/Source/icon.cpp
@@ -341,8 +341,12 @@
// calculate size
size_t group_size = sizeof(IconGroupHeader) // header
+ order.size() * SIZEOF_RSRC_ICON_GROUP_ENTRY; // entries
+ size_t padding = group_size % sizeof(DWORD);
+ if (padding > 0) {
+ padding = sizeof(DWORD) - padding;
+ }
- data_size = group_size // group header
+ data_size = group_size + padding // group header
+ sizeof(DWORD) * 2 // offset and size of group header
+ (sizeof(DWORD) * 2) * icon2.size() // offset and size per entry
+ sizeof(DWORD); // terminator
@@ -358,13 +362,16 @@
LPBYTE seeker = uninst_data;
// fill group header
- *(LPDWORD) seeker = FIX_ENDIAN_INT32((UINT32)group_size);
+ *(LPDWORD) seeker = FIX_ENDIAN_INT32((UINT32)(group_size + padding));
seeker += sizeof(DWORD);
*(LPDWORD) seeker = 0;
seeker += sizeof(DWORD);
memcpy(seeker, group, group_size);
seeker += group_size;
+ for (;padding > 0; padding--) {
+ *(seeker++) = '\0';
+ }
// fill entries
for (i = 0; i < icon2.size(); i++)