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++)

Reply via email to