xref: /wasmtime-44.0.1/crates/fuzzing/src/lib.rs (revision b570b4fc)
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