blob: 974a50edc11f545457f382d8bfa1b34e2265ac00 [file] [log] [blame] [view]
# Run a fuzzer
Once you have [built your fuzzer](build-a-fuzzer.md#fx-set), there are a few ways to execute it.
## Run a fuzzer on a Fuchsia device {#run-on-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][options]{:.external}.
Note: `ffx fuzz` is currently an [experimental plugin][experimental_plugin]. It is not yet available
via the SDK and must be enabled before use by running `ffx config set fuzzing true`.
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:
<pre class="devsite-terminal">
list [-p <pattern>]
</pre>
* To connect to a fuzzer, starting it if needed:
<pre class="devsite-terminal">
attach <url> [-o <output>]
</pre>
* To get option(s) from a fuzzer:
<pre class="devsite-terminal">
get [<name>]
</pre>
* To set options on a fuzzer:
<pre class="devsite-terminal">
set <name> <value>
</pre>
* To add an input to a fuzzer's corpus:
<pre class="devsite-terminal">
add <input> [--seed]
</pre>
* To test a specific input with a fuzzer:
<pre class="devsite-terminal">
try <input>
</pre>
* To generate inputs and fuzz the target:
<pre class="devsite-terminal">
run [--runs <runs>] [--time <time>]
</pre>
* To clear extraneous bytes from an error input:
<pre class="devsite-terminal">
cleanse <input>
</pre>
* To reduce the size of an error input:
<pre class="devsite-terminal">
minimize <input> [--runs <runs>] [--time <time>]
</pre>
* To compact the attached fuzzer's corpus:
<pre class="devsite-terminal">
merge [--corpus <corpus>]
</pre>
* To get a fuzzer's execution status:
<pre class="devsite-terminal">
status
</pre>
* To retrieve the attached fuzzer's corpus:
<pre class="devsite-terminal">
fetch [--corpus <corpus>] [--seed]
</pre>
* To disconnect from a fuzzer without stopping it:
<pre class="devsite-terminal">
detach
</pre>
* To stop the attached fuzzer:
<pre class="devsite-terminal">
stop
</pre>
* To disconnect from a fuzzer and exit the shell:
<pre class="devsite-terminal">
exit
</pre>
* To clear the screen:
<pre class="devsite-terminal">
clear
</pre>
* To print the command history for the shell:
<pre class="devsite-terminal">
history
</pre>
Most commands require a fuzzer to be attached to the shell using the fuzzer's
[component URL][glossary.component_url]. Once attached, the fuzzer component remains alive until it
is stopped, either by the `stop` command or by [Test Manager][test_manager]. You can detach from a
fuzzer and reattach to it later.
Note: if `attach` reports that the component cannot be found or cannot be resolved, check that the
component is available to the [component resolver][component-resolvers]. Typically this means
ensuring [`fx serve`][fx-serve] is running or including your fuzzer in the
[base image][package-deployment-options] via `fx set ... --with-base <package>`.
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:
```sh
attach fuchsia-pkg://fuchsia.com/my-fuzzers#meta/my-fuzzer.cm # 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.
stop
exit
```
## Run a fuzzer on a development host {#run-on-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][options]{:external} to your `fx host-tool` invocation.
For example:
<pre class="devsite-terminal">
fx host-tool my_host_fuzzer -runs=1000
</pre>
You can see all available options by using `-help=1`:
<pre class="devsite-terminal">
fx host-tool my_host_fuzzer -help=1
</pre>
## Run a fuzzer on ClusterFuzz {#run-on-clusterfuzz}
This is the easiest and most recommended way to run a fuzzer after initial development. To run your
fuzzer on [ClusterFuzz][clusterfuzz]{:.external}, you simply need to ensure it is a [GN][fuchsia-gn]
dependency of `//bundles/buildbot/core`. Practically, this means including it in your code's "tests"
GN target.
For example:
```
group("tests") {
deps = [
":existing-unittest-package",
":my-fuzzers",
]
}
```
If you are unsure if your fuzzer is included in the dependency graph, you can check using `gn path`.
For example:
<pre class="devsite-terminal">
fx gn path out/default //bundles/buildbot/core <var>path-to-fuzzer</var>
</pre>
For `//examples/fuzzers`, this yields:
<pre>
//bundles/buildbot/core --[public]-->
//examples:examples --[private]-->
//examples/fuzzers:fuzzers
1 non-data path found. It is not public.
</pre>
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](handle-results.md#clusterfuzz-bugs).
[component-resolvers]: /docs/concepts/components/v2/capabilities/resolver.md
[clusterfuzz]: https://google.github.io/clusterfuzz/
[experimental_plugin]: /docs/development/tools/ffx/development/plugin-experimental.md
[fuchsia-gn]: /docs/development/build/build_system/intro.md
[fx-serve]: /tools/devshell/serve
[glossary.component_url]: /docs/glossary/README.md#component_url
[options]: https://llvm.org/docs/LibFuzzer.html#options
[package-deployment-options]: /docs/development/build/fx.md#package_deployment_options
[test_manager]: /docs/development/testing/components/test_runner_framework.md#the_test_manager