Common Options and Workflows
Using Jazzer standalone
java -cp <classpath>;<path/to/jazzer.jar>;<path/to/jazzer-junit.jar> com.code_intelligence.jazzer.Jazzer --target_class=<fuzz-test-class> [args...]
To call Jazzer directly you need to pass it the project classpath, the path to the jazzer.jar
and jazzer-junit.jar
along with the Jazzer main class com.code_intelligence.jazzer.Jazzer
and target class that contains the fuzz test.
Optionally you can add other Jazzer arguments with double dash command-line flags. Because Jazzer is based on libFuzzer, you can add all available libFuzzer arguments with single dash command-line flags. Please refer to libFuzzer for documentation.
Recommended JVM options
-XX:-OmitStackTraceInFastThrow
: Ensures that stack traces are emitted even on hot code paths. This may hurt performance if your fuzz test frequently throws and catches exceptions, but also helps find flaky bugs.-XX:+UseParallelGC
: Optimizes garbage collection for high throughput rather than low latency.-XX:+CriticalJNINatives
: Improves the runtime performance of Jazzer's instrumentation (supported with JDK 17 and earlier).-XX:+EnableDynamicAgentLoading
: Silences a warning with JDK 21 and later triggered by the Java agent that Jazzer attaches to instrument the fuzzed code.
Passing arguments
Jazzer provides multiple configuration settings. You can obtain the value of a setting item some_opt
from the
following sources in increasing order of precedence:
- the default value
META-INF/MANIFEST.MF
attributeJazzer-Some-Opt
on the classpath- the
JAZZER_SOME_OPT
environment variable - the
jazzer.some_opt
system property - the
jazzer.some_opt
JUnit configuration parameter - the
--some_opt
CLI parameter
Minimizing a crashing input
With the following argument you can minimize a crashing input to find the smallest input that reproduces the same "bug":
-minimize_crash=1 <path/to/crashing_input>
Coverage instrumentation
The Jazzer agent inserts coverage markers into the JVM bytecode during class loading.
It's possible to restrict instrumentation to only a subset of classes with the --instrumentation_includes
flag.
This is especially useful if coverage inside specific packages is of higher interest,
for example, the user library under test rather than an external parsing library in which the fuzzer is likely to get
lost.
Similarly, there is --instrumentation_excludes
to exclude specific classes from instrumentation.
Both flags take a list of glob patterns for the java class name separated by colon:
--instrumentation_includes=com.my_com.**:com.other_com.** --instrumentation_excludes=com.my_com.crypto.**
By default, JVM-internal classes and Java as well as Kotlin standard library classes aren't instrumented, so you don't have to exclude them manually.
Value profile
The runtime flag -use_value_profile=1
enables value profiling mode, analog to
libFuzzer.
Custom hooks
In order to obtain information about data passed into functions such as String.equals
or String.startsWith
,
Jazzer hooks invocations to these methods.
This feature is also available to fuzz targets, where you can implement custom sanitizers or stub out
methods that block the fuzzer from progressing, for example checksum verifications or random number generation.
You can declare method hooks with the @MethodHook
annotation defined in the com.code_intelligence.jazzer.api
package.
To use the compiled method hooks, they have to be available on the classpath and loaded by providing the
flag --custom_hooks
, which takes a colon-separated list of names of classes to load hooks from.
Hooks have to be loaded from separate JAR files so that Jazzer
can add it to the bootstrap class loader search.
Alternatively you can specify a list of custom hooks with the Jazzer-Hook-Classes
attribute in the fuzz test JAR's
manifest.
--keep_going
With the flag --keep_going=N
Jazzer continues fuzzing until it encountered N
unique stack traces.
--keep-going=0
keeps the fuzzer running until it meets another stop condition (for example maximum runtime).
You can ignore particular stack traces based on their DEDUP_TOKEN
by passing a comma-separated list of tokens to the
command: --ignore=<token_1>,<token2>
.
Native libraries
Jazzer supports fuzzing of native libraries loaded by the JVM, for example via System.load()
.
For the fuzzer to get coverage feedback, compile these libraries with -fsanitize=fuzzer-no-link
.
Additional sanitizers such as AddressSanitizer
or UndefinedBehaviorSanitizer
are often useful to uncover bugs
inside the native libraries. You can add them with these flags:
- AddressSanitizer:
-fsanitize=fuzzer-no-link,address
- UndefinedBehaviorSanitizer:
-fsanitize=fuzzer-no-link,undefined
(add-fno-sanitize-recover=all
to crash on UBSan reports)
Starting Jazzer with --asan
and/or --ubsan
automatically preloads the sanitizer runtimes.
Jazzer defaults to using the runtimes associated with clang
on the PATH
.
If you used a different compiler to compile the native libraries, specify it with CC
to override this default.
If no compiler is available in your runtime environment, but you have a directory that contains the required sanitizer
libraries, you can specify its path in the JAZZER_NATIVE_SANITIZERS_DIR
environment variable.
On macOS, you may see Gatekeeper warnings when using --asan
and/or --ubsan
since these flags cause the
native sanitizer libraries to be preloaded into the co-designed java
executable via DYLD_INSERT_LIBRARIES
.
Sanitizers other than AddressSanitizer
and UndefinedBehaviorSanitizer
aren't yet supported.
Furthermore, due to the nature of the JVM's Garbage Collector, LeakSanitizer
reports too many false positives and
won't be supported.