This directory contains fuzzer main functions and scripts for the Google oss-fuzz project
The main build scripts can be found here and call scripts in this directory.
The list of issues can be found here
Fuzzer build logs can be found here
Feeds fuzz-generated bytes as a JPEG 2000 bitstream to the decompressor.
OSS-Fuzz crash inputs are corrupt JPEG 2000 files that can be viewed with
a hex editor or fed directly to grk_decompress.
Mutates compression parameters (image dimensions, bit depth, number of components, codec format, progression order, DWT resolutions, code-block sizes, code-block styles, irreversibility, quality layers, tiling, MCT, tile-part generation, and HTJ2K mode). Remaining fuzz bytes fill pixel data.
Unlike the decompression fuzzer, the crash input is not a JPEG 2000 file.
It is a raw byte sequence that the FuzzStream helper inside the fuzzer
decodes into compression parameters plus pixel data. To reproduce a crash
you must run the fuzzer binary with the input file — looking at the bytes
with a hex editor is not directly useful.
cd /tmp
git clone --recursive https://github.com/GrokImageCompression/grok
git clone --depth 1 https://github.com/GrokImageCompression/grok-test-data grok-data
cd grok
mkdir build
cd build
cmake .. -DBUILD_SHARED_LIBS=OFF
make -j$(nproc)
cd ../..
cd grok/tests/fuzzers
make -j$(nproc)
Fuzzers created in /tmp/*_fuzzer, with /tmp/*_fuzzer_seed_corpus.zip corpus files.
$ /tmp/grk_decompress_fuzzer a_file_name
$ /tmp/grk_compress_fuzzer a_file_name
Requires a grok build with debug info (e.g. Debug or RelWithDebInfo).
From the repository root:
gcc -g -O0 -c tests/fuzzers/fuzzingengine.c -o /tmp/fuzzingengine.o
g++ -g -O0 -std=c++20 \
-I src/lib/core -I build/src/lib/core \
tests/fuzzers/grk_decompress_fuzzer.cpp /tmp/fuzzingengine.o \
-o build/bin/grk_decompress_fuzzer \
-Lbuild/bin -lgrokj2k -lhwy -llcms2 -lm -lpthread \
-Wl,-rpath,'$ORIGIN'
g++ -g -O0 -std=c++20 \
-I src/lib/core -I build/src/lib/core \
tests/fuzzers/grk_compress_fuzzer.cpp /tmp/fuzzingengine.o \
-o build/bin/grk_compress_fuzzer \
-Lbuild/bin -lgrokj2k -lhwy -llcms2 -lm -lpthread \
-Wl,-rpath,'$ORIGIN'
The fuzzer binaries are now in build/bin/ with full debug symbols.
To debug a crash, open VSCode and select the "Compress Fuzzer"
launch configuration from the Run and Debug panel. It will prompt for
the path to a crash input file. Set breakpoints and press F5.
When a fuzzer crashes, OSS-Fuzz reports:
- Fuzzer name — e.g.
grk_decompress_fuzzerorgrk_compress_fuzzer, so you know which path triggered the issue. - Sanitizer output — AddressSanitizer, MemorySanitizer, or UndefinedBehaviorSanitizer stack traces showing the crash location.
- Minimized test case — a small input file that reproduces the crash.
For decompression crashes the test case is a corrupt JPEG 2000 file.
For compression crashes the test case is the raw fuzz bytes consumed by
FuzzStream. Reproduce locally with:
$ python3 infra/helper.py reproduce grok grk_compress_fuzzer $FILE_NAME
or with a locally built fuzzer:
$ /tmp/grk_compress_fuzzer $FILE_NAME
(make sure that docker.io is installed)
$ git clone https://github.com/google/oss-fuzz.git
$ cd oss-fuzz
$ python3 infra/helper.py build_image grok
$ python3 infra/helper.py build_fuzzers --sanitizer address grok
Test a particular fuzzer (replace grk_decompress_fuzzer by other fuzzers like the ones generated in /tmp by "make dummyfuzzers")
$ python3 infra/helper.py run_fuzzer grok grk_decompress_fuzzer
Test a particular fuzzer on a test file:
$ python3 infra/helper.py reproduce grok grk_decompress_fuzzer $FILE_NAME
Reproducers are periodically backed up on Google Cloud. A zip file of these reproducers can be downloaded as follows:
First of all, ensure that Google Cloud SDK is installed:
$ sudo snap install google-cloud-sdk --classic
$ gcloud init
Now, we can list the contents of our fuzzer bucket:
$ gsutil ls -R gs://grok-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/**/public.zip
and then copy the zip to a local drive:
$ gsutil cp gs://grok-backup.clusterfuzz-external.appspot.com/corpus/libFuzzer/grok_grk_decompress_fuzzer/public.zip .
The following shell script run in the directory holding the reproducers will compare Grok output with kdu_expand :
( for i in *; do echo -e "${i} \n"; kdu_expand -i $i -o ../fuzz_out/$i.tiff; echo -e "\n" ;grk_decompress -i $i -o ../fuzz_out/$i.tiff; echo -e "\n\n"; done; ) | tee ~/output.txt