#1930·stb

stb_image: integer overflow in animated GIF multi-frame allocation (layers * stride)

Author: AsafMeiznerCreated Apr 10, 2026Updated Sep 8, 2026

Description

The animated GIF loader in stbi__load_gif_main (stb_image.h, lines 6965-7024) has an integer overflow in the layers * stride multiplication used for buffer allocation.

Per-frame dimensions are validated against overflow on the first frame (line 6790, stbi__mad3sizes_valid). However, the multi-frame accumulation layers * stride at lines 6994 and 7010 is NOT validated.

Both layers and stride are int. As the frame count grows, their product can overflow.

Version tested: HEAD, commit 28d546d

Affected code

// stb_image.h:6991
stride = g.w * g.h * 4;    // validated once on first frame

// stb_image.h:6994 (realloc path)
void *tmp = STBI_REALLOC_SIZED(out, out_size, layers * stride);
//                                             ^^^^^^^^^^^^^^
//                                             NO overflow check

// stb_image.h:7010 (malloc path)
out = (stbi_uc*)stbi__malloc(layers * stride);
//                           ^^^^^^^^^^^^^^
//                           NO overflow check

Triggering values

Image size stride Frames to overflow
500x500 1,000,000 2,148
320x240 307,200 6,991
100x100 40,000 53,687

A 500x500 animated GIF with 2,148 frames is within the range of real-world content (game sprites, cinemagraphs, screen recordings).

Impact

64-bit: Overflowed negative int sign-extends to huge size_t, malloc returns NULL, caught by error check. Safe (DoS only).

32-bit: Integer overflow is undefined behavior. On typical compilers with wrapping, the allocation may be undersized while the subsequent memcpy at line 7021 writes the full stride bytes - heap buffer overflow.

Suggested fix

Add overflow validation before the multiplication, using the existing safe function:

++layers;
stride = g.w * g.h * 4;

// Add this check:
if (!stbi__mad2sizes_valid(layers, stride, 0)) {
    return stbi__load_gif_main_outofmem(&g, out, delays);
}

Apply to both the malloc path (line 7010) and the realloc path (line 6994).