Coverage Report

Created: 2021-03-22 08:29

/src/wasm-tools/fuzz/fuzz_targets/incremental-parse.rs
Line
Count
Source
1
#![no_main]
2
3
use libfuzzer_sys::*;
4
use wasmparser::*;
5
use Payload::*;
6
7
// Simulate receiving chunks of data by fuzzing over a `Vec<Vec<u8>>` where each
8
// element of the outer vec is a chunk of data we received.
9
//
10
// The assertion here is that parsing everything in one go should always produce
11
// the exact same results as an incremental parse.
12
fuzz_target!(|data: Vec<Vec<u8>>| {
13
    drop(env_logger::try_init());
14
15
    // Concatenate everything together, create our expected iterator of
16
    // payloads, and then write out `input.wasm` if debugging is enabled.
17
4.67M
    let everything = data.iter().flat_map(|a| a).copied().collect::<Vec<_>>();
18
    let mut expected = Parser::new(0).parse_all(&everything);
19
    if log::log_enabled!(log::Level::Debug) {
20
        std::fs::write("input.wasm", &everything).unwrap();
21
    }
22
23
    // Create our parser as well as a stack of nested parsers for parsing nested
24
    // modules.
25
    let mut stack = Vec::new();
26
    let mut parser = Parser::new(0);
27
28
    // We'll be parsing data from `buf` starting at `pos`, and we translate
29
    // `data` into an iterator of chunks so when requested we'll take another
30
    // chunk of data and feed it in.
31
    let mut pos = 0;
32
    let mut buf = Vec::new();
33
    let mut data = data.into_iter().peekable();
34
    loop {
35
        log::debug!("parsing {}..{}", pos, buf.len());
36
        let payload = match parser.parse(&buf[pos..], data.peek().is_none()) {
37
            // If more data is requested then we're guaranteed that `data`
38
            // should have another element in its iterato, so pull that off and
39
            // add it to the end of the `buf`.
40
            Ok(Chunk::NeedMoreData(_n)) => {
41
                buf.extend(data.next().unwrap());
42
                continue;
43
            }
44
            Ok(Chunk::Parsed { consumed, payload }) => {
45
                log::debug!("parsed {} bytes", consumed);
46
                pos += consumed;
47
                payload
48
            }
49
50
            // On failure we should receive the same failure as if we did a full
51
            // parse.
52
            Err(actual) => {
53
                let expected = expected
54
                    .next()
55
                    .expect("full parse stopped early")
56
                    .err()
57
                    .expect("full parse didn't return an error");
58
                assert_eq!(expected.offset(), actual.offset());
59
                assert_eq!(expected.message(), actual.message());
60
                break;
61
            }
62
        };
63
        log::debug!("parsed payload {:?}", payload);
64
        let expected_payload = expected
65
            .next()
66
            .expect("full parse stopped early")
67
            .expect("full parse failed but incremental succeeded");
68
        match (payload, expected_payload) {
69
            (End, End) => match stack.pop() {
70
                Some(p) => parser = p,
71
                None => {
72
                    log::debug!("no more parsers");
73
                    assert!(expected.next().is_none());
74
                    break;
75
                }
76
            },
77
            (Version { num: a, range: ar }, Version { num: b, range: br }) => {
78
                assert_eq!(a, b);
79
                assert_eq!(ar, br);
80
            }
81
82
            (TypeSection(a), TypeSection(b)) => assert_eq!(a.range(), b.range()),
83
            (ImportSection(a), ImportSection(b)) => assert_eq!(a.range(), b.range()),
84
            (AliasSection(a), AliasSection(b)) => assert_eq!(a.range(), b.range()),
85
            (InstanceSection(a), InstanceSection(b)) => assert_eq!(a.range(), b.range()),
86
            (FunctionSection(a), FunctionSection(b)) => assert_eq!(a.range(), b.range()),
87
            (TableSection(a), TableSection(b)) => assert_eq!(a.range(), b.range()),
88
            (MemorySection(a), MemorySection(b)) => assert_eq!(a.range(), b.range()),
89
            (GlobalSection(a), GlobalSection(b)) => assert_eq!(a.range(), b.range()),
90
            (ExportSection(a), ExportSection(b)) => assert_eq!(a.range(), b.range()),
91
            (EventSection(a), EventSection(b)) => assert_eq!(a.range(), b.range()),
92
            (StartSection { func: a, range: ar }, StartSection { func: b, range: br }) => {
93
                assert_eq!(a, b);
94
                assert_eq!(ar, br);
95
            }
96
            (ElementSection(a), ElementSection(b)) => assert_eq!(a.range(), b.range()),
97
            (
98
                DataCountSection {
99
                    count: a,
100
                    range: ar,
101
                },
102
                DataCountSection {
103
                    count: b,
104
                    range: br,
105
                },
106
            ) => {
107
                assert_eq!(a, b);
108
                assert_eq!(ar, br);
109
            }
110
            (DataSection(a), DataSection(b)) => assert_eq!(a.range(), b.range()),
111
            (
112
                CustomSection {
113
                    name: a,
114
                    data_offset: ado,
115
                    data: ad,
116
                    range: ar,
117
                },
118
                CustomSection {
119
                    name: b,
120
                    data_offset: bdo,
121
                    data: bd,
122
                    range: br,
123
                },
124
            ) => {
125
                assert_eq!(a, b);
126
                assert_eq!(ad, bd);
127
                assert_eq!(ado, bdo);
128
                assert_eq!(ar, br);
129
            }
130
            (
131
                CodeSectionStart {
132
                    count: a,
133
                    range: ar,
134
                    size: asz,
135
                },
136
                CodeSectionStart {
137
                    count: b,
138
                    range: br,
139
                    size: bsz,
140
                },
141
            )
142
            | (
143
                ModuleSectionStart {
144
                    count: a,
145
                    range: ar,
146
                    size: asz,
147
                },
148
                ModuleSectionStart {
149
                    count: b,
150
                    range: br,
151
                    size: bsz,
152
                },
153
            ) => {
154
                assert_eq!(a, b);
155
                assert_eq!(ar, br);
156
                assert_eq!(asz, bsz);
157
            }
158
159
            (CodeSectionEntry(a), CodeSectionEntry(b)) => {
160
                assert_eq!(a.get_binary_reader().range(), b.get_binary_reader().range());
161
            }
162
            (
163
                ModuleSectionEntry {
164
                    range: ar,
165
                    parser: ap,
166
                },
167
                ModuleSectionEntry { range: br, .. },
168
            ) => {
169
                assert_eq!(ar, br);
170
                stack.push(parser);
171
                parser = ap;
172
            }
173
            (
174
                UnknownSection {
175
                    id: a,
176
                    contents: ac,
177
                    range: ar,
178
                },
179
                UnknownSection {
180
                    id: b,
181
                    contents: bc,
182
                    range: br,
183
                },
184
            ) => {
185
                assert_eq!(a, b);
186
                assert_eq!(ar, br);
187
                assert_eq!(ac, bc);
188
            }
189
190
            (a, b) => {
191
                panic!("expected {:?}\ngot {:?}", b, a);
192
            }
193
        }
194
    }
195
});