Skip to content

MCFuzz v1.0.2 -- Jazzer Pipeline Actually Works

Latest

Choose a tag to compare

@blsdncn blsdncn released this 09 May 08:56

This release fixes critical bugs in the Jazzer fuzzing pipeline that caused the v1.0.1 image to silently produce zero fuzzing iterations while reporting that the smoke test was healthy. Targets, fuzzing campaigns, and collected data are unchanged -- these are evaluator-workflow fixes so the docker image faithfully reproduces the Jazzer side of the experiment.

Note: The image is large; ensure ~6 GB of disk for the tarball plus the uncompressed image.

What was broken in v1.0.1

Four independent issues conspired to make the Jazzer docker path look healthy while doing nothing:

  1. JaCoCo + JDK 21 + Jazzer 0.24 sanitizer crash. When JaCoCo's javaagent was attached for the smoke, Jazzer's Deserialization sanitizer's <clinit> triggered ObjectOutputStream.writeObject(SERIALIZED_JAZ_ZER_INSTANCE) which asked the JVM to generate jdk/internal/reflect/GeneratedSerializationConstructorAccessor1 -- generation failed under JaCoCo's bytecode transformation, throwing NoClassDefFoundError. Jazzer's main died before the libFuzzer loop ever started. The smoke's .exec file was filled purely by JaCoCo class-loading instrumentation during JVM startup; zero actual fuzz iterations executed.
  2. Wrong gradle module cache path. run-jazzer-direct.sh defaulted GRADLE_MODULE_CACHE to $HOME/.gradle/caches/..., but the image sets GRADLE_USER_HOME=/work/.gradle-container. The classpath builder found zero jars, Netty was missing, and the longer Jazzer campaign died with NoClassDefFoundError: io/netty/handler/codec/DecoderException in ~2 seconds.
  3. RESET_OUTPUTS=1 choked on bind-mounted output dirs. The reset step did rm -rf on the output subdirs, which fails with "Device or resource busy" when those subdirs are docker bind mounts.
  4. The smoke's pass criterion was too lax -- it accepted runs where Jazzer never actually fuzzed.

What changed in v1.0.2

Five edits:

  • velocity-jazzer-integration/scripts/run-jazzer-direct.sh and run-jazzer-direct-stateless.sh:
    • GRADLE_MODULE_CACHE default now honors GRADLE_USER_HOME (falls back to $HOME/.gradle), so the classpath resolves correctly inside docker and on the host.
    • Added --disabled_hooks=com.code_intelligence.jazzer.sanitizers.Deserialization to the Jazzer args, sidestepping the JDK 21 + JaCoCo incompatibility. The other 14 sanitizers are unaffected.
    • Made WORK_DIR env-overridable so evaluators can mount a host directory there to capture campaign artifacts.
    • RESET_OUTPUTS=1 now clears the contents of output dirs rather than the dirs themselves, so it works with bind mounts.
  • scripts/spike-jazzer-jacoco-feasibility.sh:
    • Pass criterion now requires actual Done <N> runs in the Jazzer stderr (i.e. real fuzz iterations had to occur).
    • Summary now reports a fuzz_iterations field.
  • README.md and docker/README.md:
    • Fixed the AFLNet container-campaign mount target (/work/outputs -> /work/campaign-runs).
    • Updated the Jazzer container campaign to use -e WORK_DIR=/work/jazzer-campaign -v "$PWD/jazzer-campaign:/work/jazzer-campaign", so artifacts land on the host.
    • Updated the interactive-shell example with matching mounts.

Quickstart

Download and load the image:

sha256sum -c mcfuzz-aflnet-experiment-ready-*.tar.gz.sha256
gunzip -c mcfuzz-aflnet-experiment-ready-*.tar.gz | docker load

Run smoke tests:

# AFLNet
docker run --rm -v "$PWD/campaign-runs:/work/campaign-runs" mcfuzz-aflnet-experiment:ready make smoke-aflnet

# Jazzer (stateful) — fuzzing iterations now actually occur
docker run --rm -e TIME_LIMIT=30 -v "$PWD/jazzer-outputs:/work/velocity-jazzer-integration/build/jazzer-jacoco-feasibility" mcfuzz-aflnet-experiment:ready make smoke-jazzer-stateful

# Jazzer (stateless)
docker run --rm -e TIME_LIMIT=30 -v "$PWD/jazzer-outputs:/work/velocity-jazzer-integration/build/jazzer-jacoco-feasibility" mcfuzz-aflnet-experiment:ready make smoke-jazzer-stateless

See README.md for full documentation including longer campaign commands.