Skip to content

Heap buffer overflow via unchecked LZW minimum code size (ucCodeStart) #117

Description

@ByamB4

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;
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions