#![doc = include_str!("../README.md")]
#[cfg(feature = "afl")]
pub use afl::fuzz as afl_fuzz;
#[cfg(feature = "honggfuzz")]
pub use honggfuzz::fuzz as honggfuzz_fuzz;
#[doc(hidden)]
pub fn run_file<F>(mut closure: F)
where
F: FnMut(&[u8]),
{
use std::{env, fs::File, io::Read};
let file_name: String = env::args().nth(1).expect("pass in a file name as argument");
println!("Now running {file_name}");
let mut buffer: Vec<u8> = Vec::new();
let mut file = File::open(file_name).unwrap_or_else(|e| {
eprintln!("Could not open file: {e}");
std::process::exit(1);
});
file.read_to_end(&mut buffer).unwrap_or_else(|e| {
eprintln!("Could not read file: {e}");
std::process::exit(1);
});
closure(buffer.as_slice());
}
#[macro_export]
macro_rules! inner_fuzz {
(|$buf:ident| $body:block) => {
$crate::run_file(|$buf| $body);
};
(|$buf:ident: &[u8]| $body:block) => {
$crate::run_file(|$buf| $body);
};
(|$buf:ident: $dty: ty| $body:block) => {
$crate::run_file(|$buf| {
let $buf: $dty = {
let mut data = ::arbitrary::Unstructured::new($buf);
if let Ok(d) = ::arbitrary::Arbitrary::arbitrary(&mut data).map_err(|_| "") {
d
} else {
return;
}
};
$body
});
};
}
#[macro_export]
#[cfg(not(any(feature = "afl", feature = "honggfuzz")))]
macro_rules! fuzz {
( $($x:tt)* ) => {
$crate::inner_fuzz!($($x)*);
}
}
#[macro_export]
#[cfg(feature = "afl")]
macro_rules! fuzz {
( $($x:tt)* ) => {
static USE_ARGS: std::sync::LazyLock<bool> = std::sync::LazyLock::new(|| std::env::args().len() > 1);
if *USE_ARGS {
$crate::inner_fuzz!($($x)*);
} else {
$crate::afl_fuzz!($($x)*);
}
};
}
#[macro_export]
#[cfg(all(feature = "honggfuzz", not(feature = "afl")))]
macro_rules! fuzz {
( $($x:tt)* ) => {
loop {
$crate::honggfuzz_fuzz!($($x)*);
}
};
}