1 //! Fuzzing infrastructure for Wasmtime. 2 3 #![deny(missing_docs)] 4 5 pub use wasm_mutate; 6 pub use wasm_smith; 7 pub mod generators; 8 pub mod mutators; 9 pub mod oracles; 10 pub mod single_module_fuzzer; 11 12 /// One time start up initialization for fuzzing: 13 /// 14 /// * Enables `env_logger`. 15 /// 16 /// * Restricts `rayon` to a single thread in its thread pool, for more 17 /// deterministic executions. 18 /// 19 /// If a fuzz target is taking raw input bytes from the fuzzer, it is fine to 20 /// call this function in the fuzz target's oracle or in the fuzz target 21 /// itself. However, if the fuzz target takes an `Arbitrary` type, and the 22 /// `Arbitrary` implementation is not derived and does interesting things, then 23 /// the `Arbitrary` implementation should call this function, since it runs 24 /// before the fuzz target itself. 25 pub fn init_fuzzing() { 26 static INIT: std::sync::Once = std::sync::Once::new(); 27 28 INIT.call_once(|| { 29 let _ = env_logger::try_init(); 30 }); 31 } 32 33 #[cfg(test)] 34 mod test { 35 use arbitrary::{Arbitrary, Unstructured}; 36 use rand::prelude::*; 37 38 pub fn gen_until_pass<T: for<'a> Arbitrary<'a>>( 39 mut f: impl FnMut(T, &mut Unstructured<'_>) -> anyhow::Result<bool>, 40 ) -> bool { 41 let mut rng = SmallRng::seed_from_u64(0); 42 let mut buf = vec![0; 2048]; 43 let n = 3000; 44 for _ in 0..n { 45 rng.fill_bytes(&mut buf); 46 let mut u = Unstructured::new(&buf); 47 48 if let Ok(config) = u.arbitrary() { 49 if f(config, &mut u).unwrap() { 50 return true; 51 } 52 } 53 } 54 false 55 } 56 57 /// Runs `f` with random data until it returns `Ok(())` `iters` times. 58 pub fn test_n_times<T: for<'a> Arbitrary<'a>>( 59 iters: u32, 60 mut f: impl FnMut(T, &mut Unstructured<'_>) -> arbitrary::Result<()>, 61 ) { 62 let mut to_test = 0..iters; 63 let ok = gen_until_pass(|a, b| { 64 if f(a, b).is_ok() { 65 Ok(to_test.next().is_none()) 66 } else { 67 Ok(false) 68 } 69 }); 70 assert!(ok); 71 } 72 } 73