/src/wasmtime/fuzz/fuzz_targets/instantiate.rs
Line | Count | Source |
1 | | #![no_main] |
2 | | |
3 | | use libfuzzer_sys::arbitrary::{Arbitrary, Result, Unstructured}; |
4 | | use wasmtime_fuzzing::generators::Config; |
5 | | use wasmtime_fuzzing::oracles::{Timeout, instantiate}; |
6 | | use wasmtime_fuzzing::single_module_fuzzer::KnownValid; |
7 | | |
8 | | wasmtime_fuzzing::single_module_fuzzer!(execute gen_module); |
9 | | |
10 | | #[derive(Debug)] |
11 | | struct InstantiateInput { |
12 | | config: Config, |
13 | | timeout: Timeout, |
14 | | } |
15 | | |
16 | | impl<'a> Arbitrary<'a> for InstantiateInput { |
17 | 13.2k | fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> { |
18 | 13.2k | let mut config: Config = u.arbitrary()?; |
19 | | |
20 | | // Pick either fuel, duration-based, or module-based timeout. Note that |
21 | | // the module-based timeout is implemented with wasm-smith's |
22 | | // `ensure_termination` option. |
23 | 12.8k | let timeout = if u.arbitrary()? { |
24 | 8.52k | config.generate_timeout(u)? |
25 | | } else { |
26 | 4.33k | Timeout::None |
27 | | }; |
28 | | |
29 | 12.8k | Ok(InstantiateInput { config, timeout }) |
30 | 13.2k | } |
31 | | } |
32 | | |
33 | 12.7k | fn execute( |
34 | 12.7k | module: &[u8], |
35 | 12.7k | known_valid: KnownValid, |
36 | 12.7k | mut input: InstantiateInput, |
37 | 12.7k | u: &mut Unstructured<'_>, |
38 | 12.7k | ) -> Result<()> { |
39 | 12.7k | let timeout = match input.timeout { |
40 | | // If the input module isn't a "known valid" module then it can't be |
41 | | // relied on self-regulating itself, so force a timeout via epochs/fuel |
42 | | // in the configuration. |
43 | 5.01k | Timeout::None if known_valid == KnownValid::No => input.config.generate_timeout(u)?, |
44 | 10.3k | other => other, |
45 | | }; |
46 | 12.7k | instantiate(module, known_valid, &input.config, timeout); |
47 | 12.7k | Ok(()) |
48 | 12.7k | } |
49 | | |
50 | 12.8k | fn gen_module( |
51 | 12.8k | input: &mut InstantiateInput, |
52 | 12.8k | u: &mut Unstructured<'_>, |
53 | 12.8k | ) -> Result<(Vec<u8>, KnownValid)> { |
54 | | // With a small-ish chance take raw fuzz input and put it in the module to |
55 | | // stress module compilation/validation. In such a situation we can't use |
56 | | // `ensure_termination` in wasm-smith so list the timeout as `None` to time |
57 | | // out via epochs or Wasmtime-level fuel. |
58 | | // |
59 | | // Otherwise though if no timeout is configured use wasm-smith fuel to |
60 | | // ensure termination. |
61 | 12.8k | let allow_invalid_funcs = u.ratio(1, 10)?; |
62 | | |
63 | 12.8k | let default_fuel = if allow_invalid_funcs { |
64 | 1.92k | input.config.module_config.config.allow_invalid_funcs = true; |
65 | 1.92k | input.timeout = Timeout::None; |
66 | 1.92k | None |
67 | 10.9k | } else if let Timeout::None = input.timeout { |
68 | 3.10k | Some(1000) |
69 | | } else { |
70 | 7.84k | None |
71 | | }; |
72 | 12.8k | let module = input.config.generate(u, default_fuel)?; |
73 | 12.7k | let known_valid = if allow_invalid_funcs { |
74 | 1.92k | KnownValid::No |
75 | | } else { |
76 | 10.8k | KnownValid::Yes |
77 | | }; |
78 | 12.7k | Ok((module.to_bytes(), known_valid)) |
79 | 12.8k | } |