Skip to main content
← All libraries
Image · C

How to fuzz libjpeg-turbo

SIMD-accelerated JPEG codec — performance optimisations add uncommon code paths.

libjpeg-turbo's SIMD fast paths and its legacy libjpeg API compatibility layer create multiple partially-tested code routes. JPEG's variable-length Huffman streams are notoriously hard to get right at boundary conditions, and crashes here affect Android, macOS, and most image-processing pipelines.

Common bug classes

  • Heap buffer overflow in Huffman entropy decoder
  • Out-of-bounds write in upsampling and colour conversion
  • Integer overflow in image dimension validation
  • Divide-by-zero in DCT quantisation table handling
  • Use-after-free in progressive JPEG scan reassembly

Recommended setup

Fuzzers

  • AFL++
  • libFuzzer
  • Honggfuzz

Sanitizers

  • ASan
  • UBSan

Harness scaffold

#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include <jpeglib.h>
#include <setjmp.h>

struct err_mgr { struct jpeg_error_mgr pub; jmp_buf jb; };
static void on_error(j_common_ptr cinfo) {
  struct err_mgr *e = (struct err_mgr *)cinfo->err;
  longjmp(e->jb, 1);
}

int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
  struct jpeg_decompress_struct cinfo;
  struct err_mgr jerr;
  cinfo.err = jpeg_std_error(&jerr.pub);
  jerr.pub.error_exit = on_error;
  if (setjmp(jerr.jb)) { jpeg_destroy_decompress(&cinfo); return 0; }
  jpeg_create_decompress(&cinfo);
  jpeg_mem_src(&cinfo, data, size);
  jpeg_read_header(&cinfo, TRUE);
  jpeg_start_decompress(&cinfo);
  size_t row_sz = cinfo.output_width * cinfo.output_components;
  JSAMPARRAY buf = (*cinfo.mem->alloc_sarray)(
      (j_common_ptr)&cinfo, JPOOL_IMAGE, row_sz, 1);
  while (cinfo.output_scanline < cinfo.output_height)
    jpeg_read_scanlines(&cinfo, buf, 1);
  jpeg_finish_decompress(&cinfo);
  jpeg_destroy_decompress(&cinfo);
  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-11813
  • CVE-2020-17541
Start fuzzing libjpeg-turbo on Fuzze.rs →

Push the harness above + a Dockerfile. First month 50% off.