diff --git a/example/src/main.rs b/example/src/main.rs index 6b6c5ff..beb9913 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -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") + + }); } diff --git a/src/lib.rs b/src/lib.rs index 92b0faf..2fd73dc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -243,54 +243,48 @@ extern "C" { /// # } /// ``` #[cfg(not(fuzzing))] -#[allow(unused_variables)] -pub fn fuzz(closure: F) where F: FnOnce(&[u8]) { +#[allow(unused_variables,unused_mut)] +pub fn fuzz(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(closure: F) where F: FnOnce(&[u8]) { - // sets panic hook if not already done - lazy_static::initialize(&PANIC_HOOK); +pub fn fuzz(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(); + } } }