/src/wasm-tools/fuzz/fuzz_targets/run.rs
Line | Count | Source (jump to first uncovered line) |
1 | | #![no_main] |
2 | | |
3 | | use arbitrary::Unstructured; |
4 | | use libfuzzer_sys::fuzz_target; |
5 | | use std::sync::OnceLock; |
6 | | |
7 | | // Helper macro which takes a static list of fuzzers as input which are then |
8 | | // delegated to internally based on the fuzz target selected. |
9 | | // |
10 | | // In general this fuzz target will execute a number of fuzzers all with the |
11 | | // same input. The `FUZZER` environment variable can be used to forcibly disable |
12 | | // all but one. |
13 | | macro_rules! run_fuzzers { |
14 | | ($($fuzzer:ident: $kind:ident,)*) => { |
15 | | static ENABLED: OnceLock<u32> = OnceLock::new(); |
16 | | |
17 | | fuzz_target!(|bytes: &[u8]| { |
18 | | // Lazily initialize this fuzzer in terms of logging as well as |
19 | | // enabled fuzzers via the `FUZZER` env var. |
20 | 1 | let enabled = *ENABLED.get_or_init(|| { |
21 | 1 | env_logger::init(); |
22 | 1 | let configured = std::env::var("FUZZER").ok(); |
23 | 1 | let configured = configured.as_deref(); |
24 | 1 | let mut enabled = 0; |
25 | 1 | let mut index = 0; |
26 | | |
27 | | $( |
28 | 1 | if configured.is_none() || configured == Some(stringify!($fuzzer)) { |
29 | 1 | enabled |= 1 << index; |
30 | 1 | } |
31 | 1 | index += 1; |
32 | 1 | )* |
33 | 1 | let _ = index; |
34 | 1 | |
35 | 1 | enabled |
36 | 1 | }); |
37 | | |
38 | | let mut index = 0; |
39 | | $( |
40 | | if enabled & (1 << index) != 0 { |
41 | | run_fuzzers!(@run $fuzzer $kind bytes index); |
42 | | } |
43 | | index += 1; |
44 | | )* |
45 | | let _ = index; |
46 | | }); |
47 | | }; |
48 | | |
49 | | (@run $fuzzer:ident unstructured $bytes:ident $index:ident) => { |
50 | | // Use the first byte of input as a discriminant of which fuzzer to |
51 | | // select. |
52 | | // |
53 | | // Afterwards run the specific fuzzer that the fuzz input is |
54 | | // targeted for so long as it's enabled. |
55 | | if let Some((which_fuzzer, bytes)) = $bytes.split_first() { |
56 | | if *which_fuzzer == $index { |
57 | | let mut u = Unstructured::new(bytes); |
58 | | let _ = wasm_tools_fuzz::$fuzzer::run(&mut u); |
59 | | } |
60 | | } |
61 | | }; |
62 | | |
63 | | (@run $fuzzer:ident string $bytes:ident $index:ident) => { |
64 | | // For string-based fuzzers run all fuzzers enabled for all |
65 | | // string-looking inputs. |
66 | | if let Ok(s) = std::str::from_utf8($bytes) { |
67 | | wasm_tools_fuzz::$fuzzer::run(s); |
68 | | } |
69 | | }; |
70 | | } |
71 | | |
72 | | run_fuzzers! { |
73 | | mutate: unstructured, |
74 | | validate_valid_module: unstructured, |
75 | | roundtrip_wit: unstructured, |
76 | | no_traps: unstructured, |
77 | | validate: unstructured, |
78 | | incremental_parse: unstructured, |
79 | | print: unstructured, |
80 | | roundtrip: string, |
81 | | text_parser: string, |
82 | | reencode: unstructured, |
83 | | wit64: unstructured, |
84 | | } |