Coverage Report

Created: 2025-01-09 07:53

/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
}