Skip to main content

wasmtime_fuzzing/oracles/
gc_access.rs

1//! Oracle for the `GcAccess` fuzz test case generator.
2
3use crate::generators;
4use wasmtime::*;
5
6/// Run the given `GcAccess` test case.
7///
8/// Panics if the generated Wasm module's embedded assertions fail, which
9/// indicates a GC bug.
10pub fn gc_access(config: generators::Config, input: generators::GcAccess) {
11    let wasm = input.to_wasm();
12    crate::oracles::log_wasm(&wasm);
13
14    let mut wasmtime_config = config.to_wasmtime();
15    wasmtime_config.wasm_gc(true);
16    wasmtime_config.wasm_function_references(true);
17    wasmtime_config.wasm_reference_types(true);
18    wasmtime_config.wasm_bulk_memory(true);
19
20    let engine = match Engine::new(&wasmtime_config) {
21        Ok(e) => e,
22        Err(_) => return,
23    };
24
25    let module = match Module::new(&engine, &wasm) {
26        Ok(m) => m,
27        Err(_) => return,
28    };
29
30    let mut linker = Linker::new(&engine);
31    linker
32        .func_wrap(
33            "wasmtime",
34            "gc",
35            |mut caller: Caller<'_, crate::oracles::StoreLimits>| {
36                let _ = caller.gc(None);
37            },
38        )
39        .unwrap();
40
41    let limits = crate::oracles::StoreLimits::new();
42    let mut store = Store::new(&engine, limits);
43    store.limiter(|s| s as &mut dyn ResourceLimiter);
44    config.configure_store_epoch_and_fuel(&mut store);
45
46    let instance = match linker.instantiate(&mut store, &module) {
47        Ok(i) => i,
48        Err(_) => return,
49    };
50
51    let run = instance
52        .get_typed_func::<(), ()>(&mut store, "run")
53        .expect("should have `run` export");
54
55    if let Err(e) = run.call(&mut store, ()) {
56        let msg = format!("{e:?}");
57        assert!(
58            !msg.contains("wasm trap: wasm `unreachable` instruction executed"),
59            "GC access assertion failure: {e:?}"
60        );
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67    use crate::generators::GcAccess;
68
69    #[test]
70    fn gc_access_oracle_passes() {
71        crate::test::test_n_times(128, |config: generators::Config, u| {
72            let input: GcAccess = u.arbitrary()?;
73            gc_access(config, input);
74            Ok(())
75        })
76    }
77}