1*33edd672SMark## Advanced options 2*33edd672SMark 3*33edd672SMark* [Passing JVM arguments](#passing-jvm-arguments) 4*33edd672SMark* [Coverage instrumentation](#coverage-instrumentation) 5*33edd672SMark* [Trace instrumentation](#trace-instrumentation) 6*33edd672SMark* [Value profile](#value-profile) 7*33edd672SMark* [Custom hooks](#custom-hooks) 8*33edd672SMark* [Suppressing stack traces](#suppressing-stack-traces) 9*33edd672SMark* [Export coverage information](#export-coverage-information) 10*33edd672SMark* [Native libraries](#native-libraries) 11*33edd672SMark* [Fuzzing mutators](#fuzzing-mutators) 12*33edd672SMark 13*33edd672SMark<!-- Created by https://github.com/ekalinin/github-markdown-toc --> 14*33edd672SMark 15*33edd672SMarkVarious command line options are available to control the instrumentation and fuzzer execution. 16*33edd672SMarkSince Jazzer is a libFuzzer-compiled binary, all positional and single dash command-line options are parsed by libFuzzer. 17*33edd672SMarkTherefore, all Jazzer options are passed via double dash command-line flags, i.e., as `--option=value` (note the `=` instead of a space). 18*33edd672SMark 19*33edd672SMarkA full list of command-line flags can be printed with the `--help` flag. 20*33edd672SMarkFor the available libFuzzer options please refer to [its documentation](https://llvm.org/docs/LibFuzzer.html) for a detailed description. 21*33edd672SMark 22*33edd672SMark### Passing JVM arguments 23*33edd672SMark 24*33edd672SMarkWhen Jazzer is started using the `jazzer` binary, it starts a JVM in which it executes the fuzz target. 25*33edd672SMarkArguments for this JVM can be provided via the `JAVA_OPTS` environment variable. 26*33edd672SMark 27*33edd672SMarkAlternatively, arguments can also be supplied via the `--jvm_args` argument. 28*33edd672SMarkMultiple arguments are delimited by the classpath separator, which is `;` on Windows and `:` else. 29*33edd672SMarkFor example, to enable preview features as well as set a maximum heap size, add the following to the Jazzer invocation: 30*33edd672SMark 31*33edd672SMark```bash 32*33edd672SMark# Windows 33*33edd672SMark--jvm_args=--enable-preview;-Xmx1000m 34*33edd672SMark# Linux & macOS 35*33edd672SMark--jvm_args=--enable-preview:-Xmx1000m 36*33edd672SMark``` 37*33edd672SMark 38*33edd672SMarkArguments specified with `--jvm_args` take precedence over those in `JAVA_OPTS`. 39*33edd672SMark 40*33edd672SMark### Coverage instrumentation 41*33edd672SMark 42*33edd672SMarkThe Jazzer agent inserts coverage markers into the JVM bytecode during class loading. 43*33edd672SMarklibFuzzer uses this information to guide its input mutations towards increased coverage. 44*33edd672SMark 45*33edd672SMarkIt is possible to restrict instrumentation to only a subset of classes with the `--instrumentation_includes` flag. 46*33edd672SMarkThis is especially useful if coverage inside specific packages is of higher interest, e.g., the user library under test rather than an external parsing library in which the fuzzer is likely to get lost. 47*33edd672SMarkSimilarly, there is `--instrumentation_excludes` to exclude specific classes from instrumentation. 48*33edd672SMarkBoth flags take a list of glob patterns for the java class name separated by colon: 49*33edd672SMark 50*33edd672SMark```bash 51*33edd672SMark--instrumentation_includes=com.my_com.**:com.other_com.** --instrumentation_excludes=com.my_com.crypto.** 52*33edd672SMark``` 53*33edd672SMark 54*33edd672SMarkBy default, JVM-internal classes and Java as well as Kotlin standard library classes are not instrumented, so these do not need to be excluded manually. 55*33edd672SMark 56*33edd672SMark### Trace instrumentation 57*33edd672SMark 58*33edd672SMarkThe agent adds additional hooks for tracing compares, integer divisions, switch statements and array indices. 59*33edd672SMarkThese hooks correspond to [clang's data flow hooks](https://clang.llvm.org/docs/SanitizerCoverage.html#tracing-data-flow). 60*33edd672SMarkThe particular instrumentation types to apply can be specified using the `--trace` flag, which accepts the following values: 61*33edd672SMark 62*33edd672SMark* `cov`: AFL-style edge coverage 63*33edd672SMark* `cmp`: compares (int, long, String) and switch cases 64*33edd672SMark* `div`: divisors in integer divisions 65*33edd672SMark* `gep`: constant array indexes 66*33edd672SMark* `indir`: call through `Method#invoke` 67*33edd672SMark* `all`: shorthand to apply all available instrumentations (except `gep`) 68*33edd672SMark 69*33edd672SMarkMultiple instrumentation types can be combined with a colon (Linux, macOS) or a semicolon (Windows). 70*33edd672SMark 71*33edd672SMark### Value profile 72*33edd672SMark 73*33edd672SMarkThe run-time flag `-use_value_profile=1` enables [libFuzzer's value profiling mode](https://llvm.org/docs/LibFuzzer.html#value-profile). 74*33edd672SMarkWhen running with this flag, the feedback about compares and constants received from Jazzer's trace instrumentation is associated with the particular bytecode location and used to provide additional coverage instrumentation. 75*33edd672SMarkSee [ExampleValueProfileFuzzer.java](../examples/src/main/java/com/example/ExampleValueProfileFuzzer.java) for a fuzz target that would be very hard to fuzz without value profile. 76*33edd672SMark 77*33edd672SMark### Custom hooks 78*33edd672SMark 79*33edd672SMarkIn order to obtain information about data passed into functions such as `String.equals` or `String.startsWith`, Jazzer hooks invocations to these methods. 80*33edd672SMarkThis functionality is also available to fuzz targets, where it can be used to implement custom sanitizers or stub out methods that block the fuzzer from progressing (e.g. checksum verifications or random number generation). 81*33edd672SMarkSee [ExampleFuzzerHooks.java](../examples/src/main/java/com/example/ExampleFuzzerHooks.java) for an example of such a hook. 82*33edd672SMarkAn example for a sanitizer can be found in [ExamplePathTraversalFuzzerHooks.java](../examples/src/main/java/com/example/ExamplePathTraversalFuzzerHooks.java). 83*33edd672SMark 84*33edd672SMarkMethod hooks can be declared using the `@MethodHook` annotation defined in the `com.code_intelligence.jazzer.api` package, which is contained in `jazzer_standalone.jar` (binary release) or in the Maven artifact [`com.code-intelligence:jazzer-api`](https://search.maven.org/search?q=g:com.code-intelligence%20a:jazzer-api). 85*33edd672SMarkSee the [javadocs of the `@MethodHook` API](https://codeintelligencetesting.github.io/jazzer-docs/jazzer-api/com/code_intelligence/jazzer/api/MethodHook.html) for more details. 86*33edd672SMark 87*33edd672SMarkTo use the compiled method hooks, they have to be available on the classpath provided by `--cp` and can then be loaded by providing the flag `--custom_hooks`, which takes a colon-separated list of names of classes to load hooks from. 88*33edd672SMarkHooks have to be loaded from separate JAR files so that Jazzer can [add it to the bootstrap class loader search](https://docs.oracle.com/javase/8/docs/api/java/lang/instrument/Instrumentation.html#appendToBootstrapClassLoaderSearch-java.util.jar.JarFile-). 89*33edd672SMarkThe list of custom hooks can alternatively be specified via the `Jazzer-Hook-Classes` attribute in the fuzz target JAR's manifest. 90*33edd672SMark 91*33edd672SMark### Suppressing stack traces 92*33edd672SMark 93*33edd672SMarkWith the flag `--keep_going=N` Jazzer continues fuzzing until `N` unique stack traces have been encountered. 94*33edd672SMark 95*33edd672SMarkParticular stack traces can also be ignored based on their `DEDUP_TOKEN` by passing a comma-separated list of tokens via `--ignore=<token_1>,<token2>`. 96*33edd672SMark 97*33edd672SMark### Export coverage information 98*33edd672SMark 99*33edd672SMarkThe internally gathered JaCoCo coverage information can be exported in human-readable and JaCoCo execution data format (`.exec`). 100*33edd672SMarkThese can help identify code areas that have not been covered by the fuzzer and thus may require more comprehensive fuzz targets or a more extensive initial corpus to reach. 101*33edd672SMark 102*33edd672SMarkThe human-readable report contains coverage information, like branch and line coverage, on file level. 103*33edd672SMarkIt's useful to get a quick overview about the overall coverage. The flag `--coverage_report=<file>` can be used to generate it. 104*33edd672SMark 105*33edd672SMarkSimilar to the JaCoCo `dump` command, the flag `--coverage_dump=<file>` specifies a coverage dump file, often called `jacoco.exec`, that is generated after the fuzzing run. It contains a binary representation of the gathered coverage data in the JaCoCo format. 106*33edd672SMark 107*33edd672SMarkThe JaCoCo `report` command can be used to generate reports based on this coverage dump. 108*33edd672SMarkThe JaCoCo CLI tools are available on their [GitHub release page](https://github.com/jacoco/jacoco/releases) as `zip` file. 109*33edd672SMarkThe report tool is located in the `lib` folder and can be used as described in the JaCoCo [CLI documentation](https://www.eclemma.org/jacoco/trunk/doc/cli.html). 110*33edd672SMarkFor example the following command generates an HTML report in the folder `report` containing all classes available in `classes.jar` and their coverage as captured in the export `coverage.exec`. 111*33edd672SMarkSource code to include in the report is searched for in `some/path/to/sources`. 112*33edd672SMarkAfter execution the `index.html` file in the output folder can be opened in a browser. 113*33edd672SMark```shell 114*33edd672SMarkjava -jar path/to/jacococli.jar report coverage.exec \ 115*33edd672SMark --classfiles classes.jar \ 116*33edd672SMark --sourcefiles some/path/to/sources \ 117*33edd672SMark --html report \ 118*33edd672SMark --name FuzzCoverageReport 119*33edd672SMark``` 120*33edd672SMark 121*33edd672SMark### Native libraries 122*33edd672SMark 123*33edd672SMarkJazzer supports fuzzing of native libraries loaded by the JVM, for example via `System.load()`. 124*33edd672SMarkFor the fuzzer to get coverage feedback, these libraries have to be compiled with `-fsanitize=fuzzer-no-link`. 125*33edd672SMark 126*33edd672SMarkAdditional sanitizers such as AddressSanitizer or UndefinedBehaviorSanitizer are often desirable to uncover bugs inside the native libraries. 127*33edd672SMarkThe required compilation flags for native libraries are as follows: 128*33edd672SMark- *AddressSanitizer*: `-fsanitize=fuzzer-no-link,address` 129*33edd672SMark- *UndefinedBehaviorSanitizer*: `-fsanitize=fuzzer-no-link,undefined` (add `-fno-sanitize-recover=all` to crash on UBSan reports) 130*33edd672SMark 131*33edd672SMarkThen, start Jazzer with `--asan` and/or `--ubsan` to automatically preload the sanitizer runtimes. 132*33edd672SMarkJazzer defaults to using the runtimes associated with `clang` on the `PATH`. 133*33edd672SMarkIf you used a different compiler to compile the native libraries, specify it with `CC` to override this default. 134*33edd672SMarkIf no compiler is available in your runtime environment (e.g. in OSS-Fuzz) but you have a directory that contains the required sanitier libraries, specify its path in `JAZZER_NATIVE_SANITIZERS_DIR`. 135*33edd672SMark 136*33edd672SMark**Note:** 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 codesigned `java` executable via `DYLD_INSERT_LIBRARIES`. 137*33edd672SMark 138*33edd672SMarkSanitizers other than AddressSanitizer and UndefinedBehaviorSanitizer are not yet supported. 139*33edd672SMarkFurthermore, due to the nature of the JVM's GC, LeakSanitizer reports too many false positives to be useful and is thus disabled. 140*33edd672SMark 141*33edd672SMarkThe fuzz targets `ExampleFuzzerWithASan` and `ExampleFuzzerWithUBSan` in the [`examples`](../examples/src/main/java/com/example) directory contain minimal working examples for fuzzing with native libraries. 142*33edd672SMarkAlso see `TurboJpegFuzzer` for a real-world example. 143*33edd672SMark 144*33edd672SMark### Fuzzing mutators 145*33edd672SMark 146*33edd672SMarkLibFuzzer API offers two functions to customize the mutation strategy which is especially useful when fuzzing functions that require structured input. 147*33edd672SMarkJazzer does not define `LLVMFuzzerCustomMutator` nor `LLVMFuzzerCustomCrossOver` and leaves the mutation strategy entirely to libFuzzer. 148*33edd672SMarkHowever, custom mutators can easily be integrated by compiling a mutator library which defines `LLVMFuzzerCustomMutator` (and optionally `LLVMFuzzerCustomCrossOver`) and pre-loading the mutator library: 149*33edd672SMark 150*33edd672SMark```bash 151*33edd672SMark# Using Bazel: 152*33edd672SMarkLD_PRELOAD=libcustom_mutator.so bazel run //:jazzer -- <arguments> 153*33edd672SMark# Using the binary release: 154*33edd672SMarkLD_PRELOAD=libcustom_mutator.so ./jazzer <arguments> 155*33edd672SMark``` 156*33edd672SMark 157