Skip to content

Commit

Permalink
The fuzzing loop in now done in the fuzzing macro
Browse files Browse the repository at this point in the history
just like in AFL.rs
closes #6
  • Loading branch information
PaulGrandperrin committed Feb 2, 2019
1 parent d6db565 commit 129de9a
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 60 deletions.
40 changes: 18 additions & 22 deletions example/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,23 @@ fn main() {
// For more information, check out the `std::panic::UnwindSafe` trait.
let mut some_global_state = 0u64;

// You have full control over the loop but
// you're supposed to call `fuzz` ad vitam aeternam
loop {
// The fuzz macro gives an arbitrary object (see `arbitrary crate`)
// to a closure-like block of code.
// For performance, it is recommended that you use the native type
// `&[u8]` when possible.
// Here, this slice will contain a "random" quantity of "random" data.
honggfuzz::fuzz!(|data: &[u8]| {
// Try to access the global state across the unwind boundary
some_global_state += 1;
// The fuzz macro gives an arbitrary object (see `arbitrary crate`)
// to a closure-like block of code.
// For performance, it is recommended that you use the native type
// `&[u8]` when possible.
// Here, this slice will contain a "random" quantity of "random" data.
honggfuzz::fuzz!(|data: &[u8]| {
// Try to access the global state across the unwind boundary
some_global_state += 1;

if data.len() != 6 {return}
if data[0] != b'q' {return}
if data[1] != b'w' {return}
if data[2] != b'e' {return}
if data[3] != b'r' {return}
if data[4] != b't' {return}
if data[5] != b'y' {return}
panic!("BOOM")

});
}
if data.len() != 6 {return}
if data[0] != b'q' {return}
if data[1] != b'w' {return}
if data[2] != b'e' {return}
if data[3] != b'r' {return}
if data[4] != b't' {return}
if data[5] != b'y' {return}
panic!("BOOM")

});
}
70 changes: 32 additions & 38 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,54 +243,48 @@ extern "C" {
/// # }
/// ```
#[cfg(not(fuzzing))]
#[allow(unused_variables)]
pub fn fuzz<F>(closure: F) where F: FnOnce(&[u8]) {
#[allow(unused_variables,unused_mut)]
pub fn fuzz<F>(mut closure: F) where F: FnMut(&[u8]) {
eprintln!("This executable hasn't been built with \"cargo hfuzz\".");
eprintln!("Try executing \"cargo hfuzz build\" and check out \"hfuzz_target\" directory.");
eprintln!("Or execute \"cargo hfuzz run TARGET\"");
std::process::exit(17);
}

// Registers a panic hook that aborts the process before unwinding.
// It is useful to abort before unwinding so that the fuzzer will then be
// able to analyse the process stack frames to tell different bugs appart.
#[cfg(all(fuzzing, not(fuzzing_debug)))]
lazy_static::lazy_static! {
static ref PANIC_HOOK: () = {
std::panic::set_hook(Box::new(|_| {
std::process::abort();
}))
};
}

#[cfg(all(fuzzing, not(fuzzing_debug)))]
pub fn fuzz<F>(closure: F) where F: FnOnce(&[u8]) {
// sets panic hook if not already done
lazy_static::initialize(&PANIC_HOOK);
pub fn fuzz<F>(mut closure: F) where F: FnMut(&[u8]) {
// Registers a panic hook that aborts the process before unwinding.
// It is useful to abort before unwinding so that the fuzzer will then be
// able to analyse the process stack frames to tell different bugs appart.
std::panic::set_hook(Box::new(|_| {
std::process::abort();
}));

// get buffer from honggfuzz runtime
let buf;
unsafe {
let mut buf_ptr: *const u8 = std::mem::uninitialized();
let mut len_ptr: usize = std::mem::uninitialized();
HF_ITER(&mut buf_ptr, &mut len_ptr);
buf = ::std::slice::from_raw_parts(buf_ptr, len_ptr);
}
// infinite fuzzing loop
loop {
// get buffer from honggfuzz runtime
let buf = unsafe {
let mut buf_ptr: *const u8 = std::mem::uninitialized();
let mut len_ptr: usize = std::mem::uninitialized();
HF_ITER(&mut buf_ptr, &mut len_ptr);
::std::slice::from_raw_parts(buf_ptr, len_ptr)
};

// We still catch unwinding panics just in case the fuzzed code modifies
// the panic hook.
// If so, the fuzzer will be unable to tell different bugs appart and you will
// only be able to find one bug at a time before fixing it to then find a new one.
// The closure is assumed to be unwind-safe, which might be unsafe. For more info, check the
// [`std::panic::UnwindSafe`] trait.
let did_panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
closure(buf);
})).is_err();
// We still catch unwinding panics just in case the fuzzed code modifies
// the panic hook.
// If so, the fuzzer will be unable to tell different bugs appart and you will
// only be able to find one bug at a time before fixing it to then find a new one.
// The closure is assumed to be unwind-safe, which might be unsafe. For more info, check the
// [`std::panic::UnwindSafe`] trait.
let did_panic = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
closure(buf);
})).is_err();

if did_panic {
// hopefully the custom panic hook will be called before and abort the
// process before the stack frames are unwinded.
std::process::abort();
if did_panic {
// hopefully the custom panic hook will be called before and abort the
// process before the stack frames are unwinded.
std::process::abort();
}
}
}

Expand Down

0 comments on commit 129de9a

Please sign in to comment.