1#![doc = include_str!("../README.md")]
2#[cfg(feature = "afl")]
3pub use afl::fuzz as afl_fuzz;
4#[cfg(feature = "honggfuzz")]
5pub use honggfuzz::fuzz as honggfuzz_fuzz;
6
7#[doc(hidden)]
10pub fn run_file<F>(mut closure: F)
11where
12 F: FnMut(&[u8]),
13{
14 use std::{env, fs::File, io::Read};
15 let file_name: String = env::args().nth(1).expect("pass in a file name as argument");
16 println!("Now running {file_name}");
17 let mut buffer: Vec<u8> = Vec::new();
18 let mut file = File::open(file_name).unwrap_or_else(|e| {
19 eprintln!("Could not open file: {e}");
20 std::process::exit(1);
21 });
22 file.read_to_end(&mut buffer).unwrap_or_else(|e| {
23 eprintln!("Could not read file: {e}");
24 std::process::exit(1);
25 });
26 closure(buffer.as_slice());
27}
28
29#[macro_export]
50macro_rules! inner_fuzz {
51 (|$buf:ident| $body:block) => {
52 $crate::run_file(|$buf| $body);
53 };
54 (|$buf:ident: &[u8]| $body:block) => {
55 $crate::run_file(|$buf| $body);
56 };
57 (|$buf:ident: $dty: ty| $body:block) => {
58 $crate::run_file(|$buf| {
59 let $buf: $dty = {
60 let mut data = ::arbitrary::Unstructured::new($buf);
61 if let Ok(d) = ::arbitrary::Arbitrary::arbitrary(&mut data).map_err(|_| "") {
62 d
63 } else {
64 return;
65 }
66 };
67 $body
68 });
69 };
70}
71
72#[macro_export]
74#[cfg(not(any(feature = "afl", feature = "honggfuzz")))]
75macro_rules! fuzz {
76 ( $($x:tt)* ) => {
77 $crate::inner_fuzz!($($x)*);
78 }
79}
80
81#[macro_export]
82#[cfg(feature = "afl")]
83macro_rules! fuzz {
84 ( $($x:tt)* ) => {
85 static USE_ARGS: std::sync::LazyLock<bool> = std::sync::LazyLock::new(|| std::env::args().len() > 1);
86 if *USE_ARGS {
87 $crate::inner_fuzz!($($x)*);
88 } else {
89 $crate::afl_fuzz!($($x)*);
90 }
91 };
92}
93
94#[macro_export]
95#[cfg(all(feature = "honggfuzz", not(feature = "afl")))]
96macro_rules! fuzz {
97 ( $($x:tt)* ) => {
98 loop {
99 $crate::honggfuzz_fuzz!($($x)*);
100 }
101 };
102}