-
Notifications
You must be signed in to change notification settings - Fork 8k
Open
Description
i discovered a resource exhaustion denial of service vulnerability in stb_image's TGA parser through fuzzing. A
malformed 19-byte TGA file claiming impossible dimensions causes allocation of 65.5 MB of memory, leading to
application crashes or system resource exhaustion.
- Type: Denial of Service (Resource Exhaustion)
- Severity: Medium-High (CVSS 7.5)
- Attack Vector: Remote (via malicious image file)
- Affected: All versions of stb_image.h tested (including latest)
- exploitability: Trivial (just load a crafted TGA file)
Any application using stb_image to load user-supplied images can be remotely crashed.
Proof of Concept
Malicious TGA File** (19 bytes):
Hex: 47 00 0a 0e 00 0a 0a 01 00 01 00 21 f9 04 01 c9 08 00 3b
Claimed dimensions: 1273 x 51457 pixels
Memory allocated: 65,504,761 bytes (62.5 MB)
Amplification: 3,447,619x from 19-byte input
Reproduction:
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
int main() {
int w, h, c;
unsigned char *img = stbi_load("dos.tga", &w, &h, &c, 0);
if (img) {
printf("Allocated: %d bytes\n", w * h * c);
// Output: Allocated: 65504761 bytes (from 19 byte file!)
stbi_image_free(img);
}
return 0;
}
Test Results:
File size: 19 bytes
Dimensions: 1273 x 51457 (1 channels)
Memory allocated: 65,504,761 bytes
I can provide the malicious TGA file if needed for testing.
Root Cause
The TGA parser does not validate image dimensions before memory allocation:
1. Reads claimed dimensions from header (no validation)
2. Calculates memory: 1273 × 51457 × 1 = 65,504,761 bytes
3. Allocates 65.5 MB without checking reasonableness
4. No validation that file size matches claimed dimensions
Suggested Fix
Add dimension validation before allocation:
#define MAX_IMAGE_DIMENSION 65536 // 64K x 64K max
// Before allocation:
if (width > MAX_IMAGE_DIMENSION || height > MAX_IMAGE_DIMENSION) {
return stbi__errpuc("image dimensions too large", "Corrupt TGA");
}
// Also check total pixels:
if ((uint64_t)width * (uint64_t)height > (uint64_t)MAX_IMAGE_DIMENSION * MAX_IMAGE_DIMENSION) {
return stbi__errpuc("image too large", "Corrupt TGA");
}
Validate file size consistency:
// File size should roughly match claimed dimensions
size_t expected_min_size = ((size_t)width * (size_t)height) / 10; // Account for compression
if (input_size < expected_min_size) {
return stbi__errpuc("file size inconsistent with dimensions", "Corrupt TGA");
}
Discovery Method
Found via AFL++ fuzzing campaign:
- Fuzzer: AFL++ v4.35c with AddressSanitizer
- Runtime: 22 hours
- Executions: 314 million test cases
- Found: 17 timeout cases (this is the first analyzed)
Additional Information
I'm happy to:
1. Provide the 19-byte malicious TGA file for testing
2. Share full technical analysis
3. Help test proposed fixes
4. Analyze the other 16 timeout cases found during fuzzingReactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels