Run a fuzzer

Once you have built your fuzzer, there are a few ways to execute it.

Run a fuzzer on a Fuchsia device

You can use the ffx fuzz tool to run a fuzzer on your local device. This is the recommended way to run your fuzzer while you are developing it. The tool is useful in that it knows how to find fuzzing-related files and knows various common options.

When fuzzing locally, it is often convenient to use the interactive fuzzing shell, which can be started using ffx fuzz shell. This shell can maintain a connection to a fuzzer, and provides utilities such as tab-completion. It supports a number of commands:

  • To list available fuzzers:
    list [-p ]
  • To connect to a fuzzer, starting it if needed:
    attach  [-o ]
  • To get option(s) from a fuzzer:
    get []
  • To set options on a fuzzer:
  • To add an input to a fuzzer's corpus:
    add  [--seed]
  • To test a specific input with a fuzzer:
  • To generate inputs and fuzz the target:
    run [--runs ] [--time 
  • To clear extraneous bytes from an error input:
  • To reduce the size of an error input:
    minimize  [--runs ] [--time 
  • To compact the attached fuzzer's corpus:
    merge [--corpus ]
  • To get a fuzzer's execution status:
  • To retrieve the attached fuzzer's corpus:
    fetch [--corpus ] [--seed]
  • To disconnect from a fuzzer without stopping it:
  • To stop the attached fuzzer:
  • To disconnect from a fuzzer and exit the shell:
  • To clear the screen:
  • To print the command history for the shell:

Most commands require a fuzzer to be attached to the shell using the fuzzer's component_url . Once attached, the fuzzer component remains alive until it is stopped, either by the stop command or by Test Manager. You can detach from a fuzzer and reattach to it later.

Several of the commands represent long-running workflows. These include the most important command, run, which performs coverage-guided fuzzing. These also include try, cleanse, minimize, and merge. All of these may execute for an indefinite amount of time.

Commands that take inputs accept both files and hexadecimal values. If the provided input is ambiguous, ffx fuzz will treat it as a hexadecimal value and print a warning. Treatment as a file can be forced by adding path elements, e.g. ./deadbeef is a file while deadbeef is a value.

Putting this all together, a typical workflow might look like the following, minus the comments:

attach fuchsia-pkg://   # Connect to the fuzzer.
run -t 60m              # Run for up to one hour.
try deadbeef            # Try a specific input, e.g. reproduce an error found by the step above.
merge -c my-local-dir   # Shrink the corpus as much as possible and save it.

Run a fuzzer on a development host

You can run host fuzzers built by the Fuchsia build system as host tools, although the extra tooling of ffx fuzz is not supported. This means you need to manually add any libFuzzer options to your fx host-tool invocation.

For example:

fx host-tool my_host_fuzzer -runs=1000

You can see all available options by using -help=1:

fx host-tool my_host_fuzzer -help=1

Run a fuzzer on ClusterFuzz

This is the easiest and most recommended way to run a fuzzer after initial development. To run your fuzzer on ClusterFuzz, you simply need to ensure it is a GN dependency of //bundles/buildbot/core. Practically, this means including it in your code's "tests" GN target.

For example:

   group("tests") {
     deps = [

If you are unsure if your fuzzer is included in the dependency graph, you can check using gn path.

For example:

fx gn path out/default //bundles/buildbot/core path-to-fuzzer

For //examples/fuzzers, this yields:

//bundles/buildbot/core --[public]-->
//examples:examples --[private]-->

1 non-data path found. It is not public.

All fuzzers in that dependency graph will be made available to ClusterFuzz to select and run. If ClusterFuzz opens bugs, you can use its outputs to reproduce its findings. See Handling results found through fuzzing.