Summary
A crafted GIF file with an invalid LZW minimum code size byte causes a massive heap buffer overflow in both DecodeLZW() and DecodeLZWTurbo(), corrupting memory far past the GIFIMAGE struct.
Vulnerability
File: gif.inl
Root cause: ucCodeStart (the LZW minimum code size byte) is read directly from the file at line 511 with no validation:
pPage->ucCodeStart = p[iOffset++]; /* initial code size */
The GIF spec requires this to be 2–8. Values > 12 cause cc (clear code) to grow exponentially, and the LZW table initialization loop writes far past the fixed-size arrays.
Exploitation path (DecodeLZW, line 1510–1528)
sMask = 0xffff << (pImage->ucCodeStart + 1); // line 1510
sMask = 0xffff - sMask;
cc = (sMask >> 1) + 1; // line 1512
for (i = 0; i < cc; i++) // line 1524
{
gifpels[PIXEL_FIRST + i] = gifpels[PIXEL_LAST + i] = (unsigned short) i;
giftabs[i] = LINK_END; // line 1527
}
With ucCodeStart = 13:
cc = 8192 (instead of max 256 for valid GIFs)
giftabs[i] writes to usGIFTable[0..8191] — array is only 4096 entries → 8192 bytes heap overflow
gifpels[PIXEL_LAST + i] writes to ucGIFPixels[4096..12287] — array is only 8192 bytes → 4096 bytes heap overflow past ucGIFPixels, through ucLineBuf, and 2048 bytes past the GIFIMAGE struct entirely
With ucCodeStart = 14:
cc = 32768 → overflows are ~10x larger (57K+ bytes past arrays)
DecodeLZWTurbo has the same issue (line 1207–1225)
codestart = pImage->ucCodeStart; // line 1207
iColors = 1 << codestart; // line 1208 — 8192+ for codestart=13
for (i = 0; i<iColors; i++) {
pSymbols[i] = iUncompressedLen + i; // line 1222 — pSymbols has 4096 entries
Secondary: OOB read at cGIFBits (line 513)
pPage->iBpp = cGIFBits[pPage->ucCodeStart]; // cGIFBits has only 9 entries
For ucCodeStart >= 9, this reads past the static array boundary.
Impact
- Heap corruption: The overflow writes deterministic values (LINK_END = 0x1718, sequential bytes) over heap memory past the GIFIMAGE struct
- Remote code execution potential: Overwriting heap metadata or adjacent objects with controlled data
- Any application loading untrusted
.gif files is affected
Suggested Fix
Add validation after reading ucCodeStart:
pPage->ucCodeStart = p[iOffset++];
if (pPage->ucCodeStart < 2 || pPage->ucCodeStart > 8) {
pPage->iError = GIF_BAD_FILE;
return 0;
}
Summary
A crafted GIF file with an invalid LZW minimum code size byte causes a massive heap buffer overflow in both
DecodeLZW()andDecodeLZWTurbo(), corrupting memory far past theGIFIMAGEstruct.Vulnerability
File:
gif.inlRoot cause:
ucCodeStart(the LZW minimum code size byte) is read directly from the file at line 511 with no validation:The GIF spec requires this to be 2–8. Values > 12 cause
cc(clear code) to grow exponentially, and the LZW table initialization loop writes far past the fixed-size arrays.Exploitation path (DecodeLZW, line 1510–1528)
With
ucCodeStart = 13:cc= 8192 (instead of max 256 for valid GIFs)giftabs[i]writes tousGIFTable[0..8191]— array is only 4096 entries → 8192 bytes heap overflowgifpels[PIXEL_LAST + i]writes toucGIFPixels[4096..12287]— array is only 8192 bytes → 4096 bytes heap overflow pastucGIFPixels, throughucLineBuf, and 2048 bytes past theGIFIMAGEstruct entirelyWith
ucCodeStart = 14:cc= 32768 → overflows are ~10x larger (57K+ bytes past arrays)DecodeLZWTurbo has the same issue (line 1207–1225)
Secondary: OOB read at cGIFBits (line 513)
For
ucCodeStart >= 9, this reads past the static array boundary.Impact
.giffiles is affectedSuggested Fix
Add validation after reading ucCodeStart: