Skip to content

Commit

Permalink
Change fuzzing API to mimic upstream's HF_ITER style
Browse files Browse the repository at this point in the history
The library code is now a lot simpler, does not use macros
and gives users a lot more control.

This solves cargo-fuzz's issue rust-fuzz/cargo-fuzz#101

This syntax is also very similar to the one in AFL.rs.
Maybe we should converge to a compatible API? rust-fuzz/afl.rs#31
  • Loading branch information
PaulGrandperrin committed Feb 9, 2018
1 parent e33b471 commit 59c1977
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 62 deletions.
43 changes: 27 additions & 16 deletions example/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
#![no_main]
#[macro_use] extern crate honggfuzz;
extern crate honggfuzz;
use honggfuzz::fuzz;

fuzz_target!(|data: &[u8]| {
if data.len() != 10 {return}
if data[0] != 'q' as u8 {return}
if data[1] != 'w' as u8 {return}
if data[2] != 'e' as u8 {return}
if data[3] != 'r' as u8 {return}
if data[4] != 't' as u8 {return}
if data[5] != 'y' as u8 {return}
if data[6] != 'u' as u8 {return}
if data[7] != 'i' as u8 {return}
if data[8] != 'o' as u8 {return}
if data[9] != 'p' as u8 {return}
panic!("BOOM")
});
fn main() {
// Here you can parse `std::env::args and
// setup / initialize your project

// You have full control over the loop but
// you're supposed to call `fuzz` ad vitam aeternam
loop {
// the fuzz function takes a closure which takes
// a reference to a slice of u8.
// This slice contains a "random" quantity of "random" data.
fuzz(|data|{
if data.len() != 10 {return}
if data[0] != 'q' as u8 {return}
if data[1] != 'w' as u8 {return}
if data[2] != 'e' as u8 {return}
if data[3] != 'r' as u8 {return}
if data[4] != 't' as u8 {return}
if data[5] != 'y' as u8 {return}
if data[6] != 'u' as u8 {return}
if data[7] != 'i' as u8 {return}
if data[8] != 'o' as u8 {return}
if data[9] != 'p' as u8 {return}
panic!("BOOM")
});
}
}
58 changes: 12 additions & 46 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,51 +82,17 @@
//!
//! This crate was inspired by those projects!

// code stolen and adapted from https://github.com/rust-fuzz/libfuzzer-sys/blob/master/src/lib.rs
#[macro_export]
macro_rules! fuzz_target {
(|$bytes:ident| $body:block) => {
#[no_mangle]
pub extern fn rust_fuzzer_test_input($bytes: &[u8]) {
$body
}
extern "C" {
fn HF_ITER(buf_ptr: *mut *const u8, len_ptr: *mut usize );
}

#[export_name="LLVMFuzzerTestOneInput"]
pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
::std::panic::catch_unwind(|| unsafe {
let data_slice = ::std::slice::from_raw_parts(data, size);
rust_fuzzer_test_input(data_slice);
}).err().map(|_| ::std::process::abort());
0
}
};
(|$data:ident: &[u8]| $body:block) => {
fuzz_target!(|$data| $body);
};
(|$data:ident: $dty: ty| $body:block) => {
extern crate arbitrary;

#[no_mangle]
pub extern fn rust_fuzzer_test_input(bytes: &[u8]) {
use arbitrary::{Arbitrary, RingBuffer};

let $data: $dty = if let Ok(d) = RingBuffer::new(bytes, bytes.len()).and_then(|mut b|{
Arbitrary::arbitrary(&mut b).map_err(|_| "")
}) {
d
} else {
return
};
$body
}

#[export_name="LLVMFuzzerTestOneInput"]
pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
::std::panic::catch_unwind(|| unsafe {
let data_slice = ::std::slice::from_raw_parts(data, size);
rust_fuzzer_test_input(data_slice);
}).err().map(|_| ::std::process::abort());
0
}
};
pub fn fuzz<F>(closure: F) where F: Fn(&[u8]) {
let buf;
unsafe {
let mut buf_ptr: *const u8 = std::mem::uninitialized();
let mut len_ptr: usize = 0;
HF_ITER(&mut buf_ptr, &mut len_ptr);
buf = ::std::slice::from_raw_parts(buf_ptr, len_ptr);
}
closure(buf);
}

0 comments on commit 59c1977

Please sign in to comment.