Screen recording of AFL running on Rust code. The code under test is
examples/hello.rs in this repository.
What is it?
Fuzz testing is a software testing technique used to find security and stability issues by providing pseudo-random data as input to the software. American fuzzy lop is a popular, effective, and modern fuzz testing tool. This library, afl.rs, allows one to run AFL on code written in the Rust programming language .
- Nightly build of Rust from any time after January 24, 2016 (this issue prevented compatibility with previous builds of Rust)
- C++ compiler that supports C++11
- afl.rs needs to compile against a version of LLVM that matches
rustc‘s. The easy solution (if you can wait on a slow build) is to build
rustcfrom source and put it in your
PATH. Then afl.rs’sbuild script will find
llvm-configautomatically. Otherwise, the environment variable
LLVM_CONFIGshould hold the path to
llvm-configwhen you build afl.rs.
Because of these relatively strict requirements, there is a Vagrantfile provided that assists in bootstraping an afl.rs compatible environment. View the README in the
vagrant/ directory for more information.
First, add this project as a Cargo dependency:
[dependencies] afl = "0.1" afl-plugin = "0.1"
Then you can add afl instrumentation to one or more crates:
You will also need a test executable that exercises the instrumented functions, in a deterministic way based on input from stdin. This executable should link the
afl run-time library:
extern crate afl;
This will produce a binary that you can pass to
afl-fuzz in the usual manner. afl instrumentation adds some run-time overhead, so it’s a good candidate for conditional compilation , perhaps through a Cargo feature :
# You may need to add `optional = true` to the above dependencies. [features] afl = ["afl-plugin", "afl"]
// Active only with `cargo [...] --feature afl` #![cfg_attr(feature = "afl", feature(plugin))] #![cfg_attr(feature = "afl", plugin(afl_plugin))]
C++ code will be compiled by default with
g++ , though one can specify a different C++ compiler by setting the
CXX environment variable to point to a different compiler binary.
To look for logic errors in safe Rust code, use the
no-landing-pads rustc flag upon compilation of the AFL entrypoint. This causes the fuzzer to treat any Rust panic as a crash. Examples of usage:
rustc -Z no-landing-pads
cargo rustc -- -Z no-landing-pads
If your program has a slow set-up phase that does not depend on the input data, you can set
AFL_DEFER_FORKSRV=1 for a substantial speed-up, provided that you insert a call to
afl::init() after the set-up and before any dependence on input. There are various other caveats, described in the section "Bonus feature: deferred instrumentation" in
llvm_mode/README.llvm distributed with afl. See also
examples/deferred-init.rs in this repository.
See the afl documentation for other configuration variables. Some of these are set at compile time in
config.h . For the most part they only affect
afl-fuzz itself, and will work fine with this library. However, if you change
MAP_SIZE , or
FORKSRV_FD , you should update this library’s
src/config.h to match.
- brotli-rs:#2, #3 , #4 , #5 , #6 , #7 , #8 , #9 , #10 , #11 , #12
- image:#414, #473 , #474 , #477
- mp4parse-rust:#2, #4 , #5 , #6
- rustc:#24275, #24276
- rustc-serialize:#109, #110
- serde:#75, #77 , #82
- Logic errors intendril and itshtml5ever integration
These bugs aren’t nearly as serious as the memory-safety issues afl has discovered in C and C++ projects. That’s because Rust is memory-safe by default, but also because not many people have tried afl.rs yet! Over time we will update this section with the most interesting bugs, whether they’re logic errors or memory-safety problems arising from
unsafe code. Pull requests are welcome!