From 59c197757feb99d140b6b89162cd299b361d3d95 Mon Sep 17 00:00:00 2001 From: Paul Grandperrin Date: Fri, 9 Feb 2018 13:44:23 +0100 Subject: [PATCH] Change fuzzing API to mimic upstream's HF_ITER style 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 https://github.com/rust-fuzz/cargo-fuzz/issues/101 This syntax is also very similar to the one in AFL.rs. Maybe we should converge to a compatible API? https://github.com/rust-fuzz/afl.rs/issues/31 --- example/src/main.rs | 43 ++++++++++++++++++++------------- src/lib.rs | 58 ++++++++++----------------------------------- 2 files changed, 39 insertions(+), 62 deletions(-) diff --git a/example/src/main.rs b/example/src/main.rs index 7b311de..6a5e815 100644 --- a/example/src/main.rs +++ b/example/src/main.rs @@ -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") + }); + } +} diff --git a/src/lib.rs b/src/lib.rs index c5a7571..b07a4a3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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(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); } \ No newline at end of file