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