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