Path: blob/main/crates/environ/fuzz/fuzz_targets/fact-valid-module.rs
1693 views
//! A simple fuzzer for FACT1//!2//! This is an intentionally small fuzzer which is intended to only really be3//! used during the development of FACT itself when generating adapter modules.4//! This creates arbitrary adapter signatures and then generates the required5//! trampoline for that adapter ensuring that the final output wasm module is a6//! valid wasm module. This doesn't actually validate anything about the7//! correctness of the trampoline, only that it's valid wasm.89#![no_main]1011use arbitrary::Unstructured;12use libfuzzer_sys::fuzz_target;13use wasmtime_environ::{ScopeVec, Tunables, component::*};14use wasmtime_test_util::component_fuzz::{MAX_TYPE_DEPTH, TestCase, Type};1516const TYPE_COUNT: usize = 50;17const MAX_ARITY: u32 = 5;1819#[derive(Debug)]20struct GenAdapter<'a> {21test: TestCase<'a>,22// TODO: Add these arbitrary options and thread them into23// `Declarations::make_component`, or alternatively pass an `Unstructured`24// into that method to make arbitrary choices for these things.25//26// post_return: bool,27// lift_memory64: bool,28// lower_memory64: bool,29}3031fuzz_target!(|data: &[u8]| {32let _ = target(data);33});3435fn target(data: &[u8]) -> arbitrary::Result<()> {36drop(env_logger::try_init());3738let mut u = Unstructured::new(data);3940// First generate a set of type to select from.41let mut type_fuel = 1000;42let mut types = Vec::new();43for _ in 0..u.int_in_range(1..=TYPE_COUNT)? {44// Only discount fuel if the generation was successful,45// otherwise we'll get more random data and try again.46types.push(Type::generate(&mut u, MAX_TYPE_DEPTH, &mut type_fuel)?);47}4849// Next generate a static API test case driven by the above types.50let mut params = Vec::new();51let mut result = None;52for _ in 0..u.int_in_range(0..=MAX_ARITY)? {53params.push(u.choose(&types)?);54}55if u.arbitrary()? {56result = Some(u.choose(&types)?);57}5859let test = TestCase {60params,61result,62encoding1: u.arbitrary()?,63encoding2: u.arbitrary()?,64};65let adapter = GenAdapter { test };6667let wat_decls = adapter.test.declarations();68let component = wat_decls.make_component();69let component = wat::parse_str(&component).unwrap();7071let mut tunables = Tunables::default_host();72tunables.debug_adapter_modules = u.arbitrary()?;7374let mut validator = wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::all());75let mut component_types = ComponentTypesBuilder::new(&validator);76let adapters = ScopeVec::new();7778Translator::new(&tunables, &mut validator, &mut component_types, &adapters)79.translate(&component)80.expect("should never generate an invalid component");8182let adapters = adapters.into_iter();83assert!(adapters.len() >= 1);84for wasm in adapters {85validator.reset();86if let Err(err) = validator.validate_all(&wasm) {87eprintln!("invalid wasm module: {err:?}");88eprintln!("adapter: {adapter:?}");89std::fs::write("invalid.wasm", &wasm).unwrap();90match wasmprinter::print_bytes(&wasm) {91Ok(s) => std::fs::write("invalid.wat", &s).unwrap(),92Err(_) => drop(std::fs::remove_file("invalid.wat")),93}94panic!("invalid adapter: {err:?}")95}96}9798Ok(())99}100101102