← All libraries
Image · C
How to fuzz libpng
The reference PNG decoder — heavily fuzzed, yet bugs keep surfacing.
libpng is the canonical PNG reference implementation shipped in essentially every OS and browser. Its chunk-driven parser and IDAT zlib decompression surface have a long history of memory-safety bugs, and any new regression directly impacts a vast install base.
Common bug classes
- •Heap buffer overflow in IDAT row decompression
- •Integer overflow in width/height chunk validation
- •Out-of-bounds read in ancillary chunk handlers (tEXt, zTXt, iTXt)
- •Use-after-free in progressive read state machine
- •Divide-by-zero in colour-space conversion
Recommended setup
Fuzzers
- → AFL++
- → libFuzzer
- → Honggfuzz
Sanitizers
- → ASan
- → UBSan
Harness scaffold
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include <setjmp.h>
#include <png.h>
static void error_fn(png_structp ps, png_const_charp msg) {
(void)msg;
longjmp(png_jmpbuf(ps), 1);
}
static void warning_fn(png_structp ps, png_const_charp msg) {
(void)ps; (void)msg;
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
png_structp ps = png_create_read_struct(PNG_LIBPNG_VER_STRING,
NULL, error_fn, warning_fn);
if (!ps) return 0;
png_infop info = png_create_info_struct(ps);
if (!info) { png_destroy_read_struct(&ps, NULL, NULL); return 0; }
if (setjmp(png_jmpbuf(ps))) {
png_destroy_read_struct(&ps, &info, NULL); return 0;
}
png_set_read_fn(ps, NULL, NULL);
/* feed via io_ptr — simplified; real harness uses membuf */
png_destroy_read_struct(&ps, &info, NULL);
return 0;
}Save this as fuzz_target.cc, build with your compiler + sanitizer flags, and you have a working starting point.
Notable CVEs found by fuzzing
- → CVE-2018-14048
- → CVE-2019-7317
Push the harness above + a Dockerfile. First month 50% off.