Writing harnesses #
In the following, we will go over Rust specific tips to optimize the results from your harnesses. For general advice, refer to Writing harnesses.
Structure-Aware fuzzing with the arbitrary crate #
The
arbitrary crate simplifies writing fuzzing harnesses. By deriving a macro, Rust structs can be targeted for fuzzing. For example, the following code requires constructing a Name
struct that owns a String
. We derived the Arbitrary macro to facilitate the construction of such a Name
.
With the arbitrary crate, we can easily write a fuzzing harness for this test, similar to the harness in Write a Fuzz test.
The cargo-fuzz tool actually supports the arbitrary crate, so we can simplify this.
Both of the above examples require the arbitrary crate to be a dependency of your library crate. In the first example, you also need to add the dependency to the Cargo.toml
in the fuzz/
directory. The second example does not require this because the arbitrary dependency of the libfuzzer_sys
dependency is used. Here is the dependency declaration you need:
As usual, the fuzz test can be started using the following command:
cargo +nightly fuzz run fuzz_target_1
The arbitrary crate essentially offers a way to deserialize byte arrays to Rust structs. However, it is limited in that it does not offer the reverse function: serializing Rust structs to byte arrays. This becomes a problem when trying to prepare a corpus of seeds. It is not possible to purposefully construct byte-arrays that construct a specific Rust struct.
Therefore, the arbitrary crate is useful only when starting from an empty corpus. This is not an issue when using cargo-fuzz because it uses libFuzzer internally, and libFuzzer supports starting from an empty corpus. However, other fuzzers like AFL++ require a seed input.