test-fuzz

At a high-level, test-fuzz is a convenient front end for afl.rs. In more concrete terms, test-fuzz is a collection of Rust macros and a Cargo subcommand that automate certain fuzzing-related tasks, most notably:

test-fuzz accomplishes these (in part) using Rust's testing facilities. For example, to generate a fuzzing corpus, test-fuzz records a target's arguments each time it is called during an invocation of cargo test. Similarly, test-fuzz implements a fuzzing harness as an additional test in a cargo-test-generated binary. This tight integration with Rust's testing facilities is what motivates the name test-fuzz.

Contents

  1. Installation
  2. Usage
  3. Components
  4. test-fuzz package features
  5. Auto-generated corpus files
  6. Environment variables
  7. Limitations
  8. Tips and tricks

Installation

sh cargo install cargo-test-fuzz

Usage

Fuzzing with test-fuzz is essentially three steps:*

  1. Identify a fuzz target:

  2. Generate a corpus by running cargo test:

    $ cargo test

  3. Fuzz your target by running cargo test-fuzz: $ cargo test-fuzz --target foo

* Some additional steps may be necessary following a reboot. AFL requires the following commands to be run as root:

Components

test_fuzz macro

Preceding a function with the test_fuzz macro indicates that the function is a fuzz target.

The primary effects of the test_fuzz macro are:

Arguments

test_fuzz_impl macro

Whenever the test_fuzz macro is used in an impl block, the impl must be preceded with the test_fuzz_impl macro. Example:

```rust

[testfuzzimpl]

impl Foo { #[test_fuzz] fn bar(&self, x: &str) { ... } } ```

The reason for this requirement is as follows. Expansion of the test_fuzz macro adds a module definition to the enclosing scope. However, a module definition cannot appear inside an impl block. Preceding the impl with the test_fuzz_impl macro causes the module to be added outside the impl block.

If you see an error like the following, it likely means a use of the test_fuzz_impl macro is missing:

error: module is not supported in `trait`s or `impl`s

test_fuzz_impl currently has no options.

cargo test-fuzz command

The cargo test-fuzz command is used to interact with fuzz targets, and to manipulate their corpora, crashes, hangs, and work queues. Example invocations include:

  1. List fuzz targets

    cargo test-fuzz --list

  2. Display target foo's corpus

    cargo test-fuzz --target foo --display-corpus

  3. Fuzz target foo

    cargo test-fuzz --target foo

  4. Replay crashes found for target foo cargo test-fuzz --target foo --replay-crashes

Usage

cargo test-fuzz [OPTIONS] [-- <args>...]

Args

<args>... Arguments for the fuzzer

Options

``` --backtrace Display backtraces

    --consolidate
        Move one target's crashes, hangs, and work queue to its corpus; to consolidate all
        targets, use --consolidate-all

    --display-concretizations
        Display concretizations

    --display-corpus
        Display corpus using uninstrumented fuzz target; to display with instrumentation, use
        --display-corpus-instrumented

    --display-crashes
        Display crashes

    --display-hangs
        Display hangs

    --display-impl-concretizations
        Display `impl` concretizations

    --display-queue
        Display work queue

    --exact
        Target name is an exact name rather than a substring

    --features <FEATURES>...
        Space or comma separated list of features to activate

-h, --help
        Print help information

    --list
        List fuzz targets

    --manifest-path <PATH>
        Path to Cargo.toml

    --no-default-features
        Do not activate the `default` feature

    --no-instrumentation
        Compile without instrumentation (for testing build process)

    --no-run
        Compile, but don't fuzz

    --no-ui
        Disable user interface

-p, --package <PACKAGE>
        Package containing fuzz target

    --persistent
        Enable persistent mode fuzzing

    --pretty-print
        Pretty-print debug output when displaying/replaying

    --replay-corpus
        Replay corpus using uninstrumented fuzz target; to replay with instrumentation, use
        --replay-corpus-instrumented

    --replay-crashes
        Replay crashes

    --replay-hangs
        Replay hangs

    --replay-queue
        Replay work queue

    --reset
        Clear fuzzing data for one target, but leave corpus intact; to reset all targets, use
        --reset-all

    --resume
        Resume target's last fuzzing session

    --run-until-crash
        Stop fuzzing once a crash is found

    --target <TARGET>
        String that fuzz target's name must contain

    --test <NAME>
        Integration test containing fuzz target

    --timeout <TIMEOUT>
        Number of milliseconds to consider a hang when fuzzing or replaying (equivalent to `--
        -t <timeout>` when fuzzing)

-V, --version
        Print version information

```

dont_care! macro

The dont_care! macro can be used to implement serde::Serialize/serde::Deserialize for types that are easy to construct and whose values you do not care to record. Intuitively, dont_care!($ty, $expr) says:

More specifically, dont_care!($ty, $expr) expands to the following:

```rust impl serde::Serialize for $ty { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer, { ().serialize(serializer) } }

impl<'de> serde::Deserialize<'de> for $ty { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { <()>::deserialize(deserializer).map(|_| $expr) } } ```

If $ty is a unit struct, then $expr can be be omitted. That is, dont_care!($ty) is equivalent to dont_care!($ty, $ty).

Warning: dont_care! is provided for convenience and may be removed in future versions of test-fuzz.

test-fuzz package features

The features in this section apply to the test-fuzz package as a whole. Enable them in test-fuzz's dependency specification as described in the The Cargo Book. For example, to enable the auto_concretize feature, use:

toml test-fuzz = { version = "1.0.1", features = ["auto_concretize"] }

The test-fuzz package currently supports the following features:

Auto-generated corpus files

cargo-test-fuzz can auto-generate values for types that implement certain traits. If all of a target's argument types implement such traits, cargo-test-fuzz can auto-generate corpus files for the target.

The traits that cargo-test-fuzz currently supports and the values generated for them are as follows:

| Trait(s) | Value(s) | | --------------------------------- | ------------------------------------------------------------------ | | Bounded | T::min_value(), T::max_value() | | Bounded + Add + One | T::min_value() + T::one() | | Bounded + Add + Div + Two | T::min_value() / T::two() + T::max_value() / T::two() | | Bounded + Add + Div + Two + One | T::min_value() / T::two() + T::max_value() / T::two() + T::one() | | Bounded + Sub + One | T::max_value() - T::one() | | Default | T::default() |

Key

Environment variables

Limitations

Tips and tricks