From: Indrek Altpere Subject: [1/2] winemenubuilder: fix crash on invalid icon entries Message-Id: Date: Thu, 28 Aug 2014 19:05:19 +0300 Fixes https://bugs.winehq.org/show_bug.cgi?id=19241 For the InnoSetup 5 crash (and likely other similar reported crashes), the issue seems to be GRPICONDIRENTRY with invalid information. The dwBytesInRes has a value that exceeds the Size value in IMAGE_RESOURCE_DATA_ENTRY, causing out-of-bounds memcpy and thus the crash. dwBytesRes value 0x40028, as mentioned by Focht and existing in the executable, seems to be the size of unpacked bitmap data (256x256x4 + 40 byte header) and not the actual size of compressed PNG bytes. Added check+clipping against the out-of-bounds read, which fixes the particular crash. Regards, Indrek diff --git a/programs/winemenubuilder/winemenubuilder.c b/programs/winemenubuilder/winemenubuilder.c index b617510..7a75d10 100644 --- a/programs/winemenubuilder/winemenubuilder.c +++ b/programs/winemenubuilder/winemenubuilder.c @@ -612,6 +612,13 @@ static int populate_module_icons(HMODULE hModule, GRPICONDIR *grpIconDir, ICONDI if ((hResData = LoadResource(hModule, hResInfo))) { BITMAPINFO *pIcon; + DWORD availableBytes = ((IMAGE_RESOURCE_DATA_ENTRY *)hResInfo)->Size; + DWORD iconBytes = grpIconDir->idEntries[i].dwBytesInRes; + if (iconBytes > availableBytes) + { + WINE_ERR("Broken GRPICONENTRY tries to use %d bytes when only %d available, clipping\n", iconBytes, availableBytes); + iconBytes = availableBytes; + } if ((pIcon = LockResource(hResData))) { iconDirEntries[validEntries].bWidth = grpIconDir->idEntries[i].bWidth; @@ -620,11 +627,11 @@ static int populate_module_icons(HMODULE hModule, GRPICONDIR *grpIconDir, ICONDI iconDirEntries[validEntries].bReserved = grpIconDir->idEntries[i].bReserved; iconDirEntries[validEntries].wPlanes = grpIconDir->idEntries[i].wPlanes; iconDirEntries[validEntries].wBitCount = grpIconDir->idEntries[i].wBitCount; - iconDirEntries[validEntries].dwBytesInRes = grpIconDir->idEntries[i].dwBytesInRes; + iconDirEntries[validEntries].dwBytesInRes = iconBytes; iconDirEntries[validEntries].dwImageOffset = *iconOffset; validEntries++; - memcpy(&icons[*iconOffset], pIcon, grpIconDir->idEntries[i].dwBytesInRes); - *iconOffset += grpIconDir->idEntries[i].dwBytesInRes; + memcpy(&icons[*iconOffset], pIcon, iconBytes); + *iconOffset += iconBytes; } FreeResource(hResData); }