Skip to content

Latest commit

 

History

History
178 lines (122 loc) · 5.23 KB

File metadata and controls

178 lines (122 loc) · 5.23 KB

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

Fuzzers

grk_decompress_fuzzer

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.

grk_compress_fuzzer

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.

Simulate fuzzer locally

Preliminary steps

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 ../..

Build fuzzers and seed corpus

cd grok/tests/fuzzers
make -j$(nproc)

Fuzzers created in /tmp/*_fuzzer, with /tmp/*_fuzzer_seed_corpus.zip corpus files.

Run a particular fuzzer

$ /tmp/grk_decompress_fuzzer a_file_name
$ /tmp/grk_compress_fuzzer a_file_name

Build fuzzers for debugging in VSCode

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.

OSS-Fuzz crash reports

When a fuzzer crashes, OSS-Fuzz reports:

  • Fuzzer name — e.g. grk_decompress_fuzzer or grk_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

Run oss-fuzz locally

(make sure that docker.io is installed)

Build grok image

$ git clone https://github.com/google/oss-fuzz.git
$ cd oss-fuzz
$ python3 infra/helper.py build_image grok

Build fuzzers with the address sanitizer (could use undefined, etc...)

$ 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

Fetch reproducer backup

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 .

Batch testing of reproducers

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