Skip to content
fuzz and property testing framework
C C++ Rust Makefile CMake Python Shell
Branch: master
Clone or download
Cameron Bytheway
Cameron Bytheway improve fuzz API
Latest commit b275d54 Nov 2, 2019
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
bolero-afl improve fuzz API Nov 2, 2019
bolero-generator improve fuzz API Nov 2, 2019
bolero-honggfuzz improve fuzz API Nov 2, 2019
bolero-libfuzzer improve fuzz API Nov 2, 2019
bolero improve fuzz API Nov 2, 2019
cargo-bolero improve fuzz API Nov 2, 2019
examples improve fuzz API Nov 2, 2019
.gitignore add initial honggfuzz support Oct 14, 2019
.rustfmt.toml initial commit Sep 6, 2019
Cargo.toml initial commit Sep 6, 2019
LICENSE add cargo metadata Sep 9, 2019
Makefile
README.md

README.md

bolero

fuzz and property testing framework

Installation

bolero is on crates.io and can be added to a project like so:

[dev-dependencies]
bolero = "0.2"

bolero includes a test generator library, bolero-generator. This is useful for crates wishing to implement generator traits for downstream applications or libraries. It is #![no_std] compatible and can be included as a regular dependency.

[dependencies]
bolero-generator = "0.2"

std support can be enabled if needed:

[dependencies]
bolero-generator = { version = "0.2", features = ["std"] }

bolero also provides a CLI program to execute fuzz tests, cargo-bolero. It can be installed globally with cargo:

$ cargo install bolero-cargo

Usage

Setup

First create a fuzz target:

$ cargo bolero new my_fuzz_target

This will create a new directory in tests/my_fuzz_target, along with a file located at tests/my_fuzz_target/main.rs. It will look something like this:

use bolero::fuzz;

fn main() {
    fuzz!(|input| {
        if input.len() < 3 {
            return;
        }

        if input[0] == 0 && input[1] == 1 && input[2] == 2 {
            panic!("you found me!");
        }
    });
}

bolero supports property testing via the same macro. More information is available in bolero-generator:

fn main() {
    fuzz!(for (a, b, c) in gen() {
        if a == 0 && b == 1 && c == 2 {
            panic!("you found me!");
        }
    });
}

The fuzz target can now be executed:

$ cargo bolero fuzz my_fuzz_target --fuzzer libfuzzer --sanitizer address

bolero supports libfuzzer, afl, and honggfuzz via the fuzzer argument.

Corpus test replay

After running a fuzz target, a corpus is generated (a set of inputs that trigger unique codepaths). This corpus can be now executed using the standard cargo test command. The corpus should either be commited to the project repository or be stored/restored from storage, like S3.

$ cargo test

     Running target/debug/deps/my_fuzz_target-9b2c2acee51634e0

running 4 tests
test corpus/3f6089c3d3533d52fe8fbc49624a9b584fe49bd7 ... ok
test corpus/7e2e044376b5b655c8a7d1df734f00ab070c8b68 ... ok
test corpus/85e53271e14006f0265921d02d4d736cdc580b0b ... ok
test corpus/72d2d4ef5fc0e8e338eeb77ef1fc73b5ed96a28f ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

Prior work

rust-fuzz

While bolero draws a lot of inspiration from the rust-fuzz organization, several improvements were made over the existing libraries:

Unified interface

rust-fuzz requires a different interface for each type of fuzzer. There is an RFC proposing a fix, but seemingly no progress has been made:

libfuzzer:

#![no_main]

#[macro_use]
extern crate libfuzzer_sys;
extern crate your_crate;

fuzz_target!(|data: &[u8]| {
    // code to fuzz goes here
});

afl:

#[macro_use]
extern crate afl;
extern crate your_crate;

fn main() {
    fuzz!(|data: &[u8]| {
        // code to fuzz goes here
    });
}

honggfuzz:

#[macro_use]
extern crate honggfuzz;
extern crate your_crate;

fn main() {
    loop {
        fuzz!(|data: &[u8]| {
            // code to fuzz goes here
        });
    }
}

bolero unifies the implementation to a single interface that supports libfuzzer, afl, and honggfuzz:

extern crate your_crate;
use bolero::fuzz;

fn main() {
    fuzz!().for_each(|input| {
        // code to fuzz goes here
    });
}

Fuzzers can be easily swapped out with the fuzzer flag passed to cargo-bolero:

$ cargo bolero fuzz --fuzzer {libfuzzer,afl,honggfuzz} my_fuzz_target

cargo test integration

bolero supports running the test corpus derived from the fuzz targets as unit tests. This is automatically done when running cargo test. The fuzz targets are also placed in the project in the standard tests directory, as opposed to creating a separate crate for fuzz tests, like the rust-fuzz crates require.

Works in stable Rust

bolero does not require nightly to execute fuzz targets in the case a sanitizer has not been specified. Most rust-fuzz crates require sanitizers to be enabled, which requires nightly.

# does not require nightly
$ cargo bolero fuzz my_fuzz_target

# requires nightly
$ cargo bolero fuzz --sanitizer address my_fuzz_target
You can’t perform that action at this time.