Skip to content

Commit

Permalink
Add afl fuzz tests (#272)
Browse files Browse the repository at this point in the history
* Add afl fuzz tests

* Add reproducer binary for protobuf files

Co-authored-by: Lucio Franco <luciofranco14@gmail.com>
  • Loading branch information
dbrgn and LucioFranco committed Jul 6, 2021
1 parent c8691b7 commit 0833d46
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Expand Up @@ -29,6 +29,8 @@ exclude = [
# The fuzz crate can't be compiled or tested without the 'cargo fuzz' command,
# so exclude it from normal builds.
"fuzz",
# Same counts for the afl fuzz targets
"afl",
]

[lib]
Expand Down
27 changes: 27 additions & 0 deletions FUZZING.md
@@ -0,0 +1,27 @@
# Fuzzing

Prost ships a few fuzz tests, using both libfuzzer and aflfuzz.


## afl

To run the afl fuzz tests, first install cargo-afl:

cargo install -f afl

Then build a fuzz target and run afl on it:

cd afl/<target>/
cargo afl build --bin fuzz-target
cargo afl fuzz -i in -o out target/debug/fuzz-target

To reproduce a crash:

cd afl/<target>/
cargo build --bin reproduce
cargo run --bin reproduce -- out/crashes/<crashfile>


## libfuzzer

TODO
2 changes: 2 additions & 0 deletions afl/.gitignore
@@ -0,0 +1,2 @@
out/
core.*
18 changes: 18 additions & 0 deletions afl/proto3/Cargo.toml
@@ -0,0 +1,18 @@
[package]
name = "fuzz-target-proto3"
version = "0.1.0"
authors = ["Prost developers"]
edition = "2018"

[[bin]]
name = "fuzz-target"
path = "src/main.rs"

[[bin]]
name = "reproduce"
path = "src/reproduce.rs"

[dependencies]
afl = "0.4"
protobuf = { path = "../../protobuf/" }
tests = { path = "../../tests/" }
30 changes: 30 additions & 0 deletions afl/proto3/README.md
@@ -0,0 +1,30 @@
# proto3 fuzz tests

## Test corpus

The test message `testmessage` was created like this:

```rust
use prost::Message;
use protobuf::test_messages::proto3::TestAllTypesProto3;

fn main() {
let msg = TestAllTypesProto3 {
optional_int32: 42,
optional_fixed64: 9983748923,
optional_bool: true,
recursive_message: Some(
Box::new(TestAllTypesProto3 {
repeated_int32: vec![1, 2, 99, 50, -5],
..Default::default()
})
),
repeated_sfixed32: vec![1, -1, 1, -1],
repeated_float: vec![-1.0, 10.10, 1.337, std::f32::NAN],
..Default::default()
};
let mut buf = vec![];
msg.encode(&mut buf).unwrap();
std::fs::write("proto3-default.bin", buf).unwrap();
}
```
Empty file added afl/proto3/in/empty
Empty file.
Binary file added afl/proto3/in/testmessage
Binary file not shown.
10 changes: 10 additions & 0 deletions afl/proto3/src/main.rs
@@ -0,0 +1,10 @@
use afl::fuzz;

use protobuf::test_messages::proto3::TestAllTypesProto3;
use tests::roundtrip;

fn main() {
fuzz!(|data: &[u8]| {
let _ = roundtrip::<TestAllTypesProto3>(data).unwrap_error();
});
}
13 changes: 13 additions & 0 deletions afl/proto3/src/reproduce.rs
@@ -0,0 +1,13 @@
use protobuf::test_messages::proto3::TestAllTypesProto3;
use tests::roundtrip;

fn main() {
let args: Vec<String> = std::env::args().collect();
if args.len() != 2 {
println!("Usage: {} <path-to-crash>", args[0]);
std::process::exit(1);
}

let data = std::fs::read(&args[1]).expect(&format!("Could not open file {}", args[1]));
let _ = roundtrip::<TestAllTypesProto3>(&data).unwrap_error();
}

0 comments on commit 0833d46

Please sign in to comment.