/src/wasmtime/fuzz/fuzz_targets/compile.rs
Line | Count | Source |
1 | | //! Compile arbitrary bytes from the fuzzer as if they were Wasm, checking that |
2 | | //! compilation is deterministic. |
3 | | //! |
4 | | //! Also use `wasm-mutate` to mutate the fuzz inputs. |
5 | | |
6 | | #![no_main] |
7 | | |
8 | | use libfuzzer_sys::{fuzz_mutator, fuzz_target}; |
9 | | use wasmtime::{Config, Engine, Module, Result}; |
10 | | |
11 | 32.0k | fn create_engine() -> Engine { |
12 | 32.0k | let mut config = Config::default(); |
13 | | // Safety: the Cranelift option `regalloc_checker` does not alter |
14 | | // the generated code at all; it only does extra checking after |
15 | | // compilation. |
16 | 32.0k | unsafe { |
17 | 32.0k | config.cranelift_flag_enable("regalloc_checker"); |
18 | 32.0k | } |
19 | 32.0k | Engine::new(&config).expect("Could not construct Engine") |
20 | 32.0k | } |
21 | | |
22 | 40.6k | fn compile_and_serialize(engine: &Engine, wasm: &[u8]) -> Result<Vec<u8>> { |
23 | 40.6k | let module = Module::new(&engine, wasm)?; |
24 | 17.1k | module.serialize() |
25 | 40.6k | } |
26 | | |
27 | | fuzz_target!(|data: &[u8]| { |
28 | | let engine = create_engine(); |
29 | | wasmtime_fuzzing::oracles::log_wasm(data); |
30 | | |
31 | | if let Ok(bytes1) = compile_and_serialize(&engine, data) { |
32 | | let bytes2 = compile_and_serialize(&engine, data) |
33 | | .expect("successfully compiled once, should successfully compile again"); |
34 | | |
35 | | // NB: Don't use `assert_eq!` here because it prints out the LHS and RHS |
36 | | // to stderr on failure, which isn't helpful here since it is just a |
37 | | // huge serialized binary. |
38 | | assert!(bytes1 == bytes2, "Wasm compilation should be deterministic"); |
39 | | } |
40 | | }); |
41 | | |
42 | | fuzz_mutator!(|data: &mut [u8], size: usize, max_size: usize, seed: u32| { |
43 | | // Half of the time use libfuzzer's built in mutators, and the other half of |
44 | | // the time use `wasm-mutate`. |
45 | | if seed.count_ones() % 2 == 0 { |
46 | | libfuzzer_sys::fuzzer_mutate(data, size, max_size) |
47 | | } else { |
48 | | wasmtime_fuzzing::mutators::wasm_mutate( |
49 | | data, |
50 | | size, |
51 | | max_size, |
52 | | seed, |
53 | | libfuzzer_sys::fuzzer_mutate, |
54 | | ) |
55 | | } |
56 | | }); |