Coverage Report

Created: 2025-10-12 07:32

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