//! Fuzzing infrastructure for Wasmtime.12#![deny(missing_docs)]34use std::pin::Pin;5use std::task::{Context, Poll, Waker};67pub use wasm_mutate;8pub use wasm_smith;9pub mod generators;10pub mod mutators;11pub mod oom;12pub mod oracles;13pub mod single_module_fuzzer;1415/// 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 more20/// deterministic executions.21///22/// If a fuzz target is taking raw input bytes from the fuzzer, it is fine to23/// call this function in the fuzz target's oracle or in the fuzz target24/// itself. However, if the fuzz target takes an `Arbitrary` type, and the25/// `Arbitrary` implementation is not derived and does interesting things, then26/// the `Arbitrary` implementation should call this function, since it runs27/// before the fuzz target itself.28pub fn init_fuzzing() {29static INIT: std::sync::Once = std::sync::Once::new();3031INIT.call_once(|| {32let _ = env_logger::try_init();33});34}3536/// One time start up initialization for fuzzing:37///38/// * Enables `env_logger`.39///40/// * Restricts `rayon` to a single thread in its thread pool, for more41/// deterministic executions.42///43/// If a fuzz target is taking raw input bytes from the fuzzer, it is fine to44/// call this function in the fuzz target's oracle or in the fuzz target45/// itself. However, if the fuzz target takes an `Arbitrary` type, and the46/// `Arbitrary` implementation is not derived and does interesting things, then47/// the `Arbitrary` implementation should call this function, since it runs48/// before the fuzz target itself.49pub fn misc_init() {50init_fuzzing();51oracles::component_async::init();52}5354fn block_on<F: Future>(future: F) -> F::Output {55const MAX_POLLS: u32 = 100_000;5657let mut f = Box::pin(future);58let mut cx = Context::from_waker(Waker::noop());59for _ in 0..MAX_POLLS {60match f.as_mut().poll(&mut cx) {61Poll::Ready(val) => return val,62Poll::Pending => {}63}64}6566panic!("future didn't become ready")67}6869/// Helper future to yield N times before resolving.70struct YieldN(u32);7172impl Future for YieldN {73type Output = ();7475fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<()> {76if self.0 == 0 {77Poll::Ready(())78} else {79self.0 -= 1;80cx.waker().wake_by_ref();81Poll::Pending82}83}84}8586#[cfg(test)]87mod test {88use arbitrary::{Arbitrary, Unstructured};89use rand::prelude::*;9091pub fn gen_until_pass<T: for<'a> Arbitrary<'a>>(92mut f: impl FnMut(T, &mut Unstructured<'_>) -> wasmtime::Result<bool>,93) -> bool {94let mut rng = SmallRng::seed_from_u64(0);95let mut buf = vec![0; 2048];96let n = 3000;97for _ in 0..n {98rng.fill_bytes(&mut buf);99let mut u = Unstructured::new(&buf);100101if let Ok(config) = u.arbitrary() {102if f(config, &mut u).unwrap() {103return true;104}105}106}107false108}109110/// Runs `f` with random data until it returns `Ok(())` `iters` times.111pub fn test_n_times<T: for<'a> Arbitrary<'a>>(112iters: u32,113mut f: impl FnMut(T, &mut Unstructured<'_>) -> arbitrary::Result<()>,114) {115let mut to_test = 0..iters;116let ok = gen_until_pass(|a, b| {117if f(a, b).is_ok() {118Ok(to_test.next().is_none())119} else {120Ok(false)121}122});123assert!(ok);124}125}126127128