← All libraries
Image · C
How to fuzz OpenJPEG
JPEG 2000's wavelet decoder has integer-overflow-prone arithmetic at every resolution level.
JPEG 2000's multi-resolution wavelet transform and complex tile-part architecture produce arithmetic that is difficult to bound statically. OpenJPEG is the open-source reference implementation used in PDFs, medical imaging (DICOM), and digital cinema — all high-value attack surfaces.
Common bug classes
- •Heap buffer overflow in wavelet reconstruction buffer sizing
- •Integer overflow in tile-component dimension arithmetic
- •Out-of-bounds read in SOP/EPH marker parsing
- •Division by zero in quality-layer rate computation
- •Use-after-free in tile-part error recovery path
Recommended setup
Fuzzers
- → AFL++
- → libFuzzer
- → Honggfuzz
Sanitizers
- → ASan
- → UBSan
Harness scaffold
#include <stdint.h>
#include <stddef.h>
#include <openjpeg.h>
static void quiet_msg(const char *msg, void *data) {
(void)msg; (void)data;
}
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
opj_stream_t *stream = opj_stream_create_default_memory_stream(
(OPJ_BYTE *)data, size, OPJ_TRUE);
if (!stream) return 0;
opj_codec_t *codec = opj_create_decompress(OPJ_CODEC_J2K);
opj_set_error_handler(codec, quiet_msg, NULL);
opj_set_warning_handler(codec, quiet_msg, NULL);
opj_set_info_handler(codec, quiet_msg, NULL);
opj_dparameters_t params;
opj_set_default_decoder_parameters(¶ms);
opj_setup_decoder(codec, ¶ms);
opj_image_t *image = NULL;
if (opj_read_header(stream, codec, &image)) {
opj_decode(codec, stream, image);
opj_end_decompress(codec, stream);
}
if (image) opj_image_destroy(image);
opj_stream_destroy(stream);
opj_destroy_codec(codec);
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-2021-29338
- → CVE-2022-1122
Push the harness above + a Dockerfile. First month 50% off.