stb_image: integer overflow in animated GIF multi-frame allocation (layers * stride)
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).
Source: nothings/stb