1 use crate::EventSectionReader;
2 use crate::{AliasSectionReader, InstanceSectionReader};
3 use crate::{BinaryReader, BinaryReaderError, FunctionBody, Range, Result};
4 use crate::{DataSectionReader, ElementSectionReader, ExportSectionReader};
5 use crate::{FunctionSectionReader, ImportSectionReader, TypeSectionReader};
6 use crate::{GlobalSectionReader, MemorySectionReader, TableSectionReader};
7 use std::convert::TryInto;
8 use std::fmt;
9 use std::iter;
10 
11 /// An incremental parser of a binary WebAssembly module.
12 ///
13 /// This type is intended to be used to incrementally parse a WebAssembly module
14 /// as bytes become available for the module. This can also be used to parse
15 /// modules that are already entirely resident within memory.
16 ///
17 /// This primary function for a parser is the [`Parser::parse`] function which
18 /// will incrementally consume input. You can also use the [`Parser::parse_all`]
19 /// function to parse a module that is entirely resident in memory.
20 #[derive(Debug, Clone)]
21 pub struct Parser {
22     state: State,
23     offset: u64,
24     max_size: u64,
25 }
26 
27 #[derive(Debug, Clone)]
28 enum State {
29     ModuleHeader,
30     SectionStart,
31     FunctionBody { remaining: u32, len: u32 },
32     Module { remaining: u32, len: u32 },
33 }
34 
35 /// A successful return payload from [`Parser::parse`].
36 ///
37 /// On success one of two possible values can be returned, either that more data
38 /// is needed to continue parsing or a chunk of the input was parsed, indicating
39 /// how much of it was parsed.
40 #[derive(Debug)]
41 pub enum Chunk<'a> {
42     /// This can be returned at any time and indicates that more data is needed
43     /// to proceed with parsing. Zero bytes were consumed from the input to
44     /// [`Parser::parse`]. The `usize` value here is a hint as to how many more
45     /// bytes are needed to continue parsing.
46     NeedMoreData(u64),
47 
48     /// A chunk was successfully parsed.
49     Parsed {
50         /// This many bytes of the `data` input to [`Parser::parse`] were
51         /// consumed to produce `payload`.
52         consumed: usize,
53         /// The value that we actually parsed.
54         payload: Payload<'a>,
55     },
56 }
57 
58 /// Values that can be parsed from a wasm module.
59 ///
60 /// This enumeration is all possible chunks of pieces that can be parsed by a
61 /// [`Parser`] from a binary WebAssembly module. Note that for many sections the
62 /// entire section is parsed all at once, whereas other functions, like the code
63 /// section, are parsed incrementally. This is a distinction where some
64 /// sections, like the type section, are required to be fully resident in memory
65 /// (fully downloaded) before proceeding. Other sections, like the code section,
66 /// can be processed in a streaming fashion where each function is extracted
67 /// individually so it can possibly be shipped to another thread while you wait
68 /// for more functions to get downloaded.
69 ///
70 /// Note that payloads, when returned, do not indicate that the wasm module is
71 /// valid. For example when you receive a `Payload::TypeSection` the type
72 /// section itself has not yet actually been parsed. The reader returned will be
73 /// able to parse it, but you'll have to actually iterate the reader to do the
74 /// full parse. Each payload returned is intended to be a *window* into the
75 /// original `data` passed to [`Parser::parse`] which can be further processed
76 /// if necessary.
77 pub enum Payload<'a> {
78     /// Indicates the header of a WebAssembly binary.
79     ///
80     /// This header also indicates the version number that was parsed, which is
81     /// currently always 1.
82     Version {
83         /// The version number found
84         num: u32,
85         /// The range of bytes that were parsed to consume the header of the
86         /// module. Note that this range is relative to the start of the byte
87         /// stream.
88         range: Range,
89     },
90 
91     /// A type section was received, and the provided reader can be used to
92     /// parse the contents of the type section.
93     TypeSection(crate::TypeSectionReader<'a>),
94     /// A import section was received, and the provided reader can be used to
95     /// parse the contents of the import section.
96     ImportSection(crate::ImportSectionReader<'a>),
97     /// An alias section was received, and the provided reader can be used to
98     /// parse the contents of the alias section.
99     AliasSection(crate::AliasSectionReader<'a>),
100     /// An instance section was received, and the provided reader can be used to
101     /// parse the contents of the instance section.
102     InstanceSection(crate::InstanceSectionReader<'a>),
103     /// A function section was received, and the provided reader can be used to
104     /// parse the contents of the function section.
105     FunctionSection(crate::FunctionSectionReader<'a>),
106     /// A table section was received, and the provided reader can be used to
107     /// parse the contents of the table section.
108     TableSection(crate::TableSectionReader<'a>),
109     /// A memory section was received, and the provided reader can be used to
110     /// parse the contents of the memory section.
111     MemorySection(crate::MemorySectionReader<'a>),
112     /// An event section was received, and the provided reader can be used to
113     /// parse the contents of the event section.
114     EventSection(crate::EventSectionReader<'a>),
115     /// A global section was received, and the provided reader can be used to
116     /// parse the contents of the global section.
117     GlobalSection(crate::GlobalSectionReader<'a>),
118     /// An export section was received, and the provided reader can be used to
119     /// parse the contents of the export section.
120     ExportSection(crate::ExportSectionReader<'a>),
121     /// A start section was received, and the `u32` here is the index of the
122     /// start function.
123     StartSection {
124         /// The start function index
125         func: u32,
126         /// The range of bytes that specify the `func` field, specified in
127         /// offsets relative to the start of the byte stream.
128         range: Range,
129     },
130     /// An element section was received, and the provided reader can be used to
131     /// parse the contents of the element section.
132     ElementSection(crate::ElementSectionReader<'a>),
133     /// A data count section was received, and the `u32` here is the contents of
134     /// the data count section.
135     DataCountSection {
136         /// The number of data segments.
137         count: u32,
138         /// The range of bytes that specify the `count` field, specified in
139         /// offsets relative to the start of the byte stream.
140         range: Range,
141     },
142     /// A data section was received, and the provided reader can be used to
143     /// parse the contents of the data section.
144     DataSection(crate::DataSectionReader<'a>),
145     /// A custom section was found.
146     CustomSection {
147         /// The name of the custom section.
148         name: &'a str,
149         /// The offset, relative to the start of the original module, that the
150         /// `data` payload for this custom section starts at.
151         data_offset: usize,
152         /// The actual contents of the custom section.
153         data: &'a [u8],
154         /// The range of bytes that specify this whole custom section (including
155         /// both the name of this custom section and its data) specified in
156         /// offsets relative to the start of the byte stream.
157         range: Range,
158     },
159 
160     /// Indicator of the start of the code section.
161     ///
162     /// This entry is returned whenever the code section starts. The `count`
163     /// field indicates how many entries are in this code section. After
164     /// receiving this start marker you're guaranteed that the next `count`
165     /// items will be either `CodeSectionEntry` or an error will be returned.
166     ///
167     /// This, unlike other sections, is intended to be used for streaming the
168     /// contents of the code section. The code section is not required to be
169     /// fully resident in memory when we parse it. Instead a [`Parser`] is
170     /// capable of parsing piece-by-piece of a code section.
171     CodeSectionStart {
172         /// The number of functions in this section.
173         count: u32,
174         /// The range of bytes that represent this section, specified in
175         /// offsets relative to the start of the byte stream.
176         range: Range,
177         /// The size, in bytes, of the remaining contents of this section.
178         ///
179         /// This can be used in combination with [`Parser::skip_section`]
180         /// where the caller will know how many bytes to skip before feeding
181         /// bytes into `Parser` again.
182         size: u32,
183     },
184 
185     /// An entry of the code section, a function, was parsed.
186     ///
187     /// This entry indicates that a function was successfully received from the
188     /// code section, and the payload here is the window into the original input
189     /// where the function resides. Note that the function itself has not been
190     /// parsed, it's only been outlined. You'll need to process the
191     /// `FunctionBody` provided to test whether it parses and/or is valid.
192     CodeSectionEntry(crate::FunctionBody<'a>),
193 
194     /// Indicator of the start of the module code section.
195     ///
196     /// This behaves the same as the `CodeSectionStart` payload being returned.
197     /// You're guaranteed the next `count` items will be of type
198     /// `ModuleSectionEntry`.
199     ModuleSectionStart {
200         /// The number of inline modules in this section.
201         count: u32,
202         /// The range of bytes that represent this section, specified in
203         /// offsets relative to the start of the byte stream.
204         range: Range,
205         /// The size, in bytes, of the remaining contents of this section.
206         size: u32,
207     },
208 
209     /// An entry of the module code section, a module, was parsed.
210     ///
211     /// This variant is special in that it returns a sub-`Parser`. Upon
212     /// receiving a `ModuleSectionEntry` it is expected that the returned
213     /// `Parser` will be used instead of the parent `Parser` until the parse has
214     /// finished. You'll need to feed data into the `Parser` returned until it
215     /// returns `Payload::End`. After that you'll switch back to the parent
216     /// parser to resume parsing the rest of the module code section.
217     ///
218     /// Note that binaries will not be parsed correctly if you feed the data for
219     /// a nested module into the parent [`Parser`].
220     ModuleSectionEntry {
221         /// The parser to use to parse the contents of the nested submodule.
222         /// This parser should be used until it reports `End`.
223         parser: Parser,
224         /// The range of bytes, relative to the start of the input stream, of
225         /// the bytes containing this submodule.
226         range: Range,
227     },
228 
229     /// An unknown section was found.
230     ///
231     /// This variant is returned for all unknown sections in a wasm file. This
232     /// likely wants to be interpreted as an error by consumers of the parser,
233     /// but this can also be used to parse sections unknown to wasmparser at
234     /// this time.
235     UnknownSection {
236         /// The 8-bit identifier for this section.
237         id: u8,
238         /// The contents of this section.
239         contents: &'a [u8],
240         /// The range of bytes, relative to the start of the original data
241         /// stream, that the contents of this section reside in.
242         range: Range,
243     },
244 
245     /// The end of the WebAssembly module was reached.
246     End,
247 }
248 
249 impl Parser {
250     /// Creates a new module parser.
251     ///
252     /// Reports errors and ranges relative to `offset` provided, where `offset`
253     /// is some logical offset within the input stream that we're parsing.
new(offset: u64) -> Parser254     pub fn new(offset: u64) -> Parser {
255         Parser {
256             state: State::ModuleHeader,
257             offset,
258             max_size: u64::max_value(),
259         }
260     }
261 
262     /// Attempts to parse a chunk of data.
263     ///
264     /// This method will attempt to parse the next incremental portion of a
265     /// WebAssembly binary. Data available for the module is provided as `data`,
266     /// and the data can be incomplete if more data has yet to arrive for the
267     /// module. The `eof` flag indicates whether `data` represents all possible
268     /// data for the module and no more data will ever be received.
269     ///
270     /// There are two ways parsing can succeed with this method:
271     ///
272     /// * `Chunk::NeedMoreData` - this indicates that there is not enough bytes
273     ///   in `data` to parse a chunk of this module. The caller needs to wait
274     ///   for more data to be available in this situation before calling this
275     ///   method again. It is guaranteed that this is only returned if `eof` is
276     ///   `false`.
277     ///
278     /// * `Chunk::Parsed` - this indicates that a chunk of the input was
279     ///   successfully parsed. The payload is available in this variant of what
280     ///   was parsed, and this also indicates how many bytes of `data` was
281     ///   consumed. It's expected that the caller will not provide these bytes
282     ///   back to the [`Parser`] again.
283     ///
284     /// Note that all `Chunk` return values are connected, with a lifetime, to
285     /// the input buffer. Each parsed chunk borrows the input buffer and is a
286     /// view into it for successfully parsed chunks.
287     ///
288     /// It is expected that you'll call this method until `Payload::End` is
289     /// reached, at which point you're guaranteed that the module has completely
290     /// parsed. Note that complete parsing, for the top-level wasm module,
291     /// implies that `data` is empty and `eof` is `true`.
292     ///
293     /// # Errors
294     ///
295     /// Parse errors are returned as an `Err`. Errors can happen when the
296     /// structure of the module is unexpected, or if sections are too large for
297     /// example. Note that errors are not returned for malformed *contents* of
298     /// sections here. Sections are generally not individually parsed and each
299     /// returned [`Payload`] needs to be iterated over further to detect all
300     /// errors.
301     ///
302     /// # Examples
303     ///
304     /// An example of reading a wasm file from a stream (`std::io::Read`) and
305     /// incrementally parsing it.
306     ///
307     /// ```
308     /// use std::io::Read;
309     /// use anyhow::Result;
310     /// use wasmparser::{Parser, Chunk, Payload::*};
311     ///
312     /// fn parse(mut reader: impl Read) -> Result<()> {
313     ///     let mut buf = Vec::new();
314     ///     let mut parser = Parser::new(0);
315     ///     let mut eof = false;
316     ///     let mut stack = Vec::new();
317     ///
318     ///     loop {
319     ///         let (payload, consumed) = match parser.parse(&buf, eof)? {
320     ///             Chunk::NeedMoreData(hint) => {
321     ///                 assert!(!eof); // otherwise an error would be returned
322     ///
323     ///                 // Use the hint to preallocate more space, then read
324     ///                 // some more data into our buffer.
325     ///                 //
326     ///                 // Note that the buffer management here is not ideal,
327     ///                 // but it's compact enough to fit in an example!
328     ///                 let len = buf.len();
329     ///                 buf.extend((0..hint).map(|_| 0u8));
330     ///                 let n = reader.read(&mut buf[len..])?;
331     ///                 buf.truncate(len + n);
332     ///                 eof = n == 0;
333     ///                 continue;
334     ///             }
335     ///
336     ///             Chunk::Parsed { consumed, payload } => (payload, consumed),
337     ///         };
338     ///
339     ///         match payload {
340     ///             // Each of these would be handled individually as necessary
341     ///             Version { .. } => { /* ... */ }
342     ///             TypeSection(_) => { /* ... */ }
343     ///             ImportSection(_) => { /* ... */ }
344     ///             AliasSection(_) => { /* ... */ }
345     ///             InstanceSection(_) => { /* ... */ }
346     ///             FunctionSection(_) => { /* ... */ }
347     ///             TableSection(_) => { /* ... */ }
348     ///             MemorySection(_) => { /* ... */ }
349     ///             EventSection(_) => { /* ... */ }
350     ///             GlobalSection(_) => { /* ... */ }
351     ///             ExportSection(_) => { /* ... */ }
352     ///             StartSection { .. } => { /* ... */ }
353     ///             ElementSection(_) => { /* ... */ }
354     ///             DataCountSection { .. } => { /* ... */ }
355     ///             DataSection(_) => { /* ... */ }
356     ///
357     ///             // Here we know how many functions we'll be receiving as
358     ///             // `CodeSectionEntry`, so we can prepare for that, and
359     ///             // afterwards we can parse and handle each function
360     ///             // individually.
361     ///             CodeSectionStart { .. } => { /* ... */ }
362     ///             CodeSectionEntry(body) => {
363     ///                 // here we can iterate over `body` to parse the function
364     ///                 // and its locals
365     ///             }
366     ///
367     ///             // When parsing nested modules we need to switch which
368     ///             // `Parser` we're using.
369     ///             ModuleSectionStart { .. } => { /* ... */ }
370     ///             ModuleSectionEntry { parser: subparser, .. } => {
371     ///                 stack.push(parser);
372     ///                 parser = subparser;
373     ///             }
374     ///
375     ///             CustomSection { name, .. } => { /* ... */ }
376     ///
377     ///             // most likely you'd return an error here
378     ///             UnknownSection { id, .. } => { /* ... */ }
379     ///
380     ///             // Once we've reached the end of a module we either resume
381     ///             // at the parent module or we break out of the loop because
382     ///             // we're done.
383     ///             End => {
384     ///                 if let Some(parent_parser) = stack.pop() {
385     ///                     parser = parent_parser;
386     ///                 } else {
387     ///                     break;
388     ///                 }
389     ///             }
390     ///         }
391     ///
392     ///         // once we're done processing the payload we can forget the
393     ///         // original.
394     ///         buf.drain(..consumed);
395     ///     }
396     ///
397     ///     Ok(())
398     /// }
399     ///
400     /// # parse(&b"\0asm\x01\0\0\0"[..]).unwrap();
401     /// ```
parse<'a>(&mut self, data: &'a [u8], eof: bool) -> Result<Chunk<'a>>402     pub fn parse<'a>(&mut self, data: &'a [u8], eof: bool) -> Result<Chunk<'a>> {
403         let (data, eof) = if usize_to_u64(data.len()) > self.max_size {
404             (&data[..(self.max_size as usize)], true)
405         } else {
406             (data, eof)
407         };
408         // TODO: thread through `offset: u64` to `BinaryReader`, remove
409         // the cast here.
410         let mut reader = BinaryReader::new_with_offset(data, self.offset as usize);
411         match self.parse_reader(&mut reader, eof) {
412             Ok(payload) => {
413                 // Be sure to update our offset with how far we got in the
414                 // reader
415                 self.offset += usize_to_u64(reader.position);
416                 self.max_size -= usize_to_u64(reader.position);
417                 Ok(Chunk::Parsed {
418                     consumed: reader.position,
419                     payload,
420                 })
421             }
422             Err(e) => {
423                 // If we're at EOF then there's no way we can recover from any
424                 // error, so continue to propagate it.
425                 if eof {
426                     return Err(e);
427                 }
428 
429                 // If our error doesn't look like it can be resolved with more
430                 // data being pulled down, then propagate it, otherwise switch
431                 // the error to "feed me please"
432                 match e.inner.needed_hint {
433                     Some(hint) => Ok(Chunk::NeedMoreData(usize_to_u64(hint))),
434                     None => Err(e),
435                 }
436             }
437         }
438     }
439 
parse_reader<'a>( &mut self, reader: &mut BinaryReader<'a>, eof: bool, ) -> Result<Payload<'a>>440     fn parse_reader<'a>(
441         &mut self,
442         reader: &mut BinaryReader<'a>,
443         eof: bool,
444     ) -> Result<Payload<'a>> {
445         use Payload::*;
446 
447         match self.state {
448             State::ModuleHeader => {
449                 let start = reader.original_position();
450                 let num = reader.read_file_header()?;
451                 self.state = State::SectionStart;
452                 Ok(Version {
453                     num,
454                     range: Range {
455                         start,
456                         end: reader.original_position(),
457                     },
458                 })
459             }
460             State::SectionStart => {
461                 // If we're at eof and there are no bytes in our buffer, then
462                 // that means we reached the end of the wasm file since it's
463                 // just a bunch of sections concatenated after the module
464                 // header.
465                 if eof && reader.bytes_remaining() == 0 {
466                     return Ok(Payload::End);
467                 }
468 
469                 let id = reader.read_var_u7()? as u8;
470                 let len_pos = reader.position;
471                 let mut len = reader.read_var_u32()?;
472 
473                 // Test to make sure that this section actually fits within
474                 // `Parser::max_size`. This doesn't matter for top-level modules
475                 // but it is required for nested modules to correctly ensure
476                 // that all sections live entirely within their section of the
477                 // file.
478                 let section_overflow = self
479                     .max_size
480                     .checked_sub(usize_to_u64(reader.position))
481                     .and_then(|s| s.checked_sub(len.into()))
482                     .is_none();
483                 if section_overflow {
484                     return Err(BinaryReaderError::new("section too large", len_pos));
485                 }
486 
487                 match id {
488                     0 => {
489                         let start = reader.original_position();
490                         let range = Range {
491                             start,
492                             end: reader.original_position() + len as usize,
493                         };
494                         let mut content = subreader(reader, len)?;
495                         // Note that if this fails we can't read any more bytes,
496                         // so clear the "we'd succeed if we got this many more
497                         // bytes" because we can't recover from "eof" at this point.
498                         let name = content.read_string().map_err(clear_hint)?;
499                         Ok(Payload::CustomSection {
500                             name,
501                             data_offset: content.original_position(),
502                             data: content.remaining_buffer(),
503                             range,
504                         })
505                     }
506                     1 => section(reader, len, TypeSectionReader::new, TypeSection),
507                     2 => section(reader, len, ImportSectionReader::new, ImportSection),
508                     3 => section(reader, len, FunctionSectionReader::new, FunctionSection),
509                     4 => section(reader, len, TableSectionReader::new, TableSection),
510                     5 => section(reader, len, MemorySectionReader::new, MemorySection),
511                     6 => section(reader, len, GlobalSectionReader::new, GlobalSection),
512                     7 => section(reader, len, ExportSectionReader::new, ExportSection),
513                     8 => {
514                         let (func, range) = single_u32(reader, len, "start")?;
515                         Ok(StartSection { func, range })
516                     }
517                     9 => section(reader, len, ElementSectionReader::new, ElementSection),
518                     10 => {
519                         let start = reader.original_position();
520                         let count = delimited(reader, &mut len, |r| r.read_var_u32())?;
521                         let range = Range {
522                             start,
523                             end: reader.original_position() + len as usize,
524                         };
525                         self.state = State::FunctionBody {
526                             remaining: count,
527                             len,
528                         };
529                         Ok(CodeSectionStart {
530                             count,
531                             range,
532                             size: len,
533                         })
534                     }
535                     11 => section(reader, len, DataSectionReader::new, DataSection),
536                     12 => {
537                         let (count, range) = single_u32(reader, len, "data count")?;
538                         Ok(DataCountSection { count, range })
539                     }
540                     13 => section(reader, len, EventSectionReader::new, EventSection),
541                     14 => {
542                         let start = reader.original_position();
543                         let count = delimited(reader, &mut len, |r| r.read_var_u32())?;
544                         let range = Range {
545                             start,
546                             end: reader.original_position() + len as usize,
547                         };
548                         self.state = State::Module {
549                             remaining: count,
550                             len,
551                         };
552                         Ok(ModuleSectionStart {
553                             count,
554                             range,
555                             size: len,
556                         })
557                     }
558                     15 => section(reader, len, InstanceSectionReader::new, InstanceSection),
559                     16 => section(reader, len, AliasSectionReader::new, AliasSection),
560                     id => {
561                         let offset = reader.original_position();
562                         let contents = reader.read_bytes(len as usize)?;
563                         let range = Range {
564                             start: offset,
565                             end: offset + len as usize,
566                         };
567                         Ok(UnknownSection {
568                             id,
569                             contents,
570                             range,
571                         })
572                     }
573                 }
574             }
575 
576             // Once we hit 0 remaining incrementally parsed items, with 0
577             // remaining bytes in each section, we're done and can switch back
578             // to parsing sections.
579             State::FunctionBody {
580                 remaining: 0,
581                 len: 0,
582             }
583             | State::Module {
584                 remaining: 0,
585                 len: 0,
586             } => {
587                 self.state = State::SectionStart;
588                 self.parse_reader(reader, eof)
589             }
590 
591             // ... otherwise trailing bytes with no remaining entries in these
592             // sections indicates an error.
593             State::FunctionBody { remaining: 0, len } | State::Module { remaining: 0, len } => {
594                 debug_assert!(len > 0);
595                 let offset = reader.original_position();
596                 Err(BinaryReaderError::new(
597                     "trailing bytes at end of section",
598                     offset,
599                 ))
600             }
601 
602             // Functions are relatively easy to parse when we know there's at
603             // least one remaining and at least one byte available to read
604             // things.
605             //
606             // We use the remaining length try to read a u32 size of the
607             // function, and using that size we require the entire function be
608             // resident in memory. This means that we're reading whole chunks of
609             // functions at a time.
610             //
611             // Limiting via `Parser::max_size` (nested modules) happens above in
612             // `fn parse`, and limiting by our section size happens via
613             // `delimited`. Actual parsing of the function body is delegated to
614             // the caller to iterate over the `FunctionBody` structure.
615             State::FunctionBody { remaining, mut len } => {
616                 let body = delimited(reader, &mut len, |r| {
617                     let size = r.read_var_u32()?;
618                     let offset = r.original_position();
619                     Ok(FunctionBody::new(offset, r.read_bytes(size as usize)?))
620                 })?;
621                 self.state = State::FunctionBody {
622                     remaining: remaining - 1,
623                     len,
624                 };
625                 Ok(CodeSectionEntry(body))
626             }
627 
628             // Modules are trickier than functions. What's going to happen here
629             // is that we'll be offloading parsing to a sub-`Parser`. This
630             // sub-`Parser` will be delimited to not read past the size of the
631             // module that's specified.
632             //
633             // So the first thing that happens here is we read the size of the
634             // module. We use `delimited` to make sure the bytes specifying the
635             // size of the module are themselves within the module code section.
636             //
637             // Once we've read the size of a module, however, there's a few
638             // pieces of state that we need to update. We as a parser will not
639             // receive the next `size` bytes, so we need to update our internal
640             // bookkeeping to account for that:
641             //
642             // * The `len`, number of bytes remaining in this section, is
643             //   decremented by `size`. This can underflow, however, meaning
644             //   that the size of the module doesn't fit within the section.
645             //
646             // * Our `Parser::max_size` field needs to account for the bytes
647             //   that we're reading. Note that this is guaranteed to not
648             //   underflow, however, because whenever we parse a section header
649             //   we guarantee that its contents fit within our `max_size`.
650             //
651             // To update `len` we do that when updating `self.state`, and to
652             // update `max_size` we do that inline. Note that this will get
653             // further tweaked after we return with the bytes we read specifying
654             // the size of the module itself.
655             State::Module { remaining, mut len } => {
656                 let size = delimited(reader, &mut len, |r| r.read_var_u32())?;
657                 match len.checked_sub(size) {
658                     Some(i) => len = i,
659                     None => {
660                         return Err(BinaryReaderError::new(
661                             "Unexpected EOF",
662                             reader.original_position(),
663                         ));
664                     }
665                 }
666                 self.state = State::Module {
667                     remaining: remaining - 1,
668                     len,
669                 };
670                 let range = Range {
671                     start: reader.original_position(),
672                     end: reader.original_position() + size as usize,
673                 };
674                 self.max_size -= u64::from(size);
675                 self.offset += u64::from(size);
676                 let mut parser = Parser::new(usize_to_u64(reader.original_position()));
677                 parser.max_size = size.into();
678                 Ok(ModuleSectionEntry { parser, range })
679             }
680         }
681     }
682 
683     /// Convenience function that can be used to parse a module entirely
684     /// resident in memory.
685     ///
686     /// This function will parse the `data` provided as a WebAssembly module,
687     /// assuming that `data` represents the entire WebAssembly module.
688     ///
689     /// Note that when this function yields `ModuleSectionEntry`
690     /// no action needs to be taken with the returned parser. The parser will be
691     /// automatically switched to internally and more payloads will continue to
692     /// get returned.
parse_all<'a>( self, mut data: &'a [u8], ) -> impl Iterator<Item = Result<Payload<'a>>> + 'a693     pub fn parse_all<'a>(
694         self,
695         mut data: &'a [u8],
696     ) -> impl Iterator<Item = Result<Payload<'a>>> + 'a {
697         let mut stack = Vec::new();
698         let mut cur = self;
699         let mut done = false;
700         iter::from_fn(move || {
701             if done {
702                 return None;
703             }
704             let payload = match cur.parse(data, true) {
705                 // Propagate all errors
706                 Err(e) => return Some(Err(e)),
707 
708                 // This isn't possible because `eof` is always true.
709                 Ok(Chunk::NeedMoreData(_)) => unreachable!(),
710 
711                 Ok(Chunk::Parsed { payload, consumed }) => {
712                     data = &data[consumed..];
713                     payload
714                 }
715             };
716 
717             match &payload {
718                 // If a module ends then we either finished the current
719                 // module or, if there's a parent, we switch back to
720                 // resuming parsing the parent.
721                 Payload::End => match stack.pop() {
722                     Some(p) => cur = p,
723                     None => done = true,
724                 },
725 
726                 // When we enter a nested module then we need to update our
727                 // current parser, saving off the previous state.
728                 //
729                 // Afterwards we turn the loop again to recurse in parsing the
730                 // nested module.
731                 Payload::ModuleSectionEntry { parser, range: _ } => {
732                     stack.push(cur.clone());
733                     cur = parser.clone();
734                 }
735 
736                 _ => {}
737             }
738 
739             Some(Ok(payload))
740         })
741     }
742 
743     /// Skip parsing the code or module code section entirely.
744     ///
745     /// This function can be used to indicate, after receiving
746     /// `CodeSectionStart` or `ModuleSectionStart`, that the section
747     /// will not be parsed.
748     ///
749     /// The caller will be responsible for skipping `size` bytes (found in the
750     /// `CodeSectionStart` or `ModuleSectionStart` payload). Bytes should
751     /// only be fed into `parse` after the `size` bytes have been skipped.
752     ///
753     /// # Panics
754     ///
755     /// This function will panic if the parser is not in a state where it's
756     /// parsing the code or module code section.
757     ///
758     /// # Examples
759     ///
760     /// ```
761     /// use wasmparser::{Result, Parser, Chunk, Range, SectionReader, Payload::*};
762     ///
763     /// fn objdump_headers(mut wasm: &[u8]) -> Result<()> {
764     ///     let mut parser = Parser::new(0);
765     ///     loop {
766     ///         let payload = match parser.parse(wasm, true)? {
767     ///             Chunk::Parsed { consumed, payload } => {
768     ///                 wasm = &wasm[consumed..];
769     ///                 payload
770     ///             }
771     ///             // this state isn't possible with `eof = true`
772     ///             Chunk::NeedMoreData(_) => unreachable!(),
773     ///         };
774     ///         match payload {
775     ///             TypeSection(s) => print_range("type section", &s.range()),
776     ///             ImportSection(s) => print_range("import section", &s.range()),
777     ///             // .. other sections
778     ///
779     ///             // Print the range of the code section we see, but don't
780     ///             // actually iterate over each individual function.
781     ///             CodeSectionStart { range, size, .. } => {
782     ///                 print_range("code section", &range);
783     ///                 parser.skip_section();
784     ///                 wasm = &wasm[size as usize..];
785     ///             }
786     ///             End => break,
787     ///             _ => {}
788     ///         }
789     ///     }
790     ///     Ok(())
791     /// }
792     ///
793     /// fn print_range(section: &str, range: &Range) {
794     ///     println!("{:>40}: {:#010x} - {:#010x}", section, range.start, range.end);
795     /// }
796     /// ```
skip_section(&mut self)797     pub fn skip_section(&mut self) {
798         let skip = match self.state {
799             State::FunctionBody { remaining: _, len } | State::Module { remaining: _, len } => len,
800             _ => panic!("wrong state to call `skip_section`"),
801         };
802         self.offset += u64::from(skip);
803         self.max_size -= u64::from(skip);
804         self.state = State::SectionStart;
805     }
806 }
807 
usize_to_u64(a: usize) -> u64808 fn usize_to_u64(a: usize) -> u64 {
809     a.try_into().unwrap()
810 }
811 
812 /// Parses an entire section resident in memory into a `Payload`.
813 ///
814 /// Requires that `len` bytes are resident in `reader` and uses `ctor`/`variant`
815 /// to construct the section to return.
section<'a, T>( reader: &mut BinaryReader<'a>, len: u32, ctor: fn(&'a [u8], usize) -> Result<T>, variant: fn(T) -> Payload<'a>, ) -> Result<Payload<'a>>816 fn section<'a, T>(
817     reader: &mut BinaryReader<'a>,
818     len: u32,
819     ctor: fn(&'a [u8], usize) -> Result<T>,
820     variant: fn(T) -> Payload<'a>,
821 ) -> Result<Payload<'a>> {
822     let offset = reader.original_position();
823     let payload = reader.read_bytes(len as usize)?;
824     // clear the hint for "need this many more bytes" here because we already
825     // read all the bytes, so it's not possible to read more bytes if this
826     // fails.
827     let reader = ctor(payload, offset).map_err(clear_hint)?;
828     Ok(variant(reader))
829 }
830 
831 /// Creates a new `BinaryReader` from the given `reader` which will be reading
832 /// the first `len` bytes.
833 ///
834 /// This means that `len` bytes must be resident in memory at the time of this
835 /// reading.
subreader<'a>(reader: &mut BinaryReader<'a>, len: u32) -> Result<BinaryReader<'a>>836 fn subreader<'a>(reader: &mut BinaryReader<'a>, len: u32) -> Result<BinaryReader<'a>> {
837     let offset = reader.original_position();
838     let payload = reader.read_bytes(len as usize)?;
839     Ok(BinaryReader::new_with_offset(payload, offset))
840 }
841 
842 /// Reads a section that is represented by a single uleb-encoded `u32`.
single_u32<'a>(reader: &mut BinaryReader<'a>, len: u32, desc: &str) -> Result<(u32, Range)>843 fn single_u32<'a>(reader: &mut BinaryReader<'a>, len: u32, desc: &str) -> Result<(u32, Range)> {
844     let range = Range {
845         start: reader.original_position(),
846         end: reader.original_position() + len as usize,
847     };
848     let mut content = subreader(reader, len)?;
849     // We can't recover from "unexpected eof" here because our entire section is
850     // already resident in memory, so clear the hint for how many more bytes are
851     // expected.
852     let index = content.read_var_u32().map_err(clear_hint)?;
853     if !content.eof() {
854         return Err(BinaryReaderError::new(
855             format!("Unexpected content in the {} section", desc),
856             content.original_position(),
857         ));
858     }
859     Ok((index, range))
860 }
861 
862 /// Attempts to parse using `f`.
863 ///
864 /// This will update `*len` with the number of bytes consumed, and it will cause
865 /// a failure to be returned instead of the number of bytes consumed exceeds
866 /// what `*len` currently is.
delimited<'a, T>( reader: &mut BinaryReader<'a>, len: &mut u32, f: impl FnOnce(&mut BinaryReader<'a>) -> Result<T>, ) -> Result<T>867 fn delimited<'a, T>(
868     reader: &mut BinaryReader<'a>,
869     len: &mut u32,
870     f: impl FnOnce(&mut BinaryReader<'a>) -> Result<T>,
871 ) -> Result<T> {
872     let start = reader.position;
873     let ret = f(reader)?;
874     *len = match (reader.position - start)
875         .try_into()
876         .ok()
877         .and_then(|i| len.checked_sub(i))
878     {
879         Some(i) => i,
880         None => return Err(BinaryReaderError::new("Unexpected EOF", start)),
881     };
882     Ok(ret)
883 }
884 
885 impl Default for Parser {
default() -> Parser886     fn default() -> Parser {
887         Parser::new(0)
888     }
889 }
890 
891 impl fmt::Debug for Payload<'_> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result892     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
893         use Payload::*;
894         match self {
895             CustomSection {
896                 name,
897                 data_offset,
898                 data: _,
899                 range,
900             } => f
901                 .debug_struct("CustomSection")
902                 .field("name", name)
903                 .field("data_offset", data_offset)
904                 .field("range", range)
905                 .field("data", &"...")
906                 .finish(),
907             Version { num, range } => f
908                 .debug_struct("Version")
909                 .field("num", num)
910                 .field("range", range)
911                 .finish(),
912             TypeSection(_) => f.debug_tuple("TypeSection").field(&"...").finish(),
913             ImportSection(_) => f.debug_tuple("ImportSection").field(&"...").finish(),
914             AliasSection(_) => f.debug_tuple("AliasSection").field(&"...").finish(),
915             InstanceSection(_) => f.debug_tuple("InstanceSection").field(&"...").finish(),
916             FunctionSection(_) => f.debug_tuple("FunctionSection").field(&"...").finish(),
917             TableSection(_) => f.debug_tuple("TableSection").field(&"...").finish(),
918             MemorySection(_) => f.debug_tuple("MemorySection").field(&"...").finish(),
919             EventSection(_) => f.debug_tuple("EventSection").field(&"...").finish(),
920             GlobalSection(_) => f.debug_tuple("GlobalSection").field(&"...").finish(),
921             ExportSection(_) => f.debug_tuple("ExportSection").field(&"...").finish(),
922             ElementSection(_) => f.debug_tuple("ElementSection").field(&"...").finish(),
923             DataSection(_) => f.debug_tuple("DataSection").field(&"...").finish(),
924             StartSection { func, range } => f
925                 .debug_struct("StartSection")
926                 .field("func", func)
927                 .field("range", range)
928                 .finish(),
929             DataCountSection { count, range } => f
930                 .debug_struct("DataCountSection")
931                 .field("count", count)
932                 .field("range", range)
933                 .finish(),
934             CodeSectionStart { count, range, size } => f
935                 .debug_struct("CodeSectionStart")
936                 .field("count", count)
937                 .field("range", range)
938                 .field("size", size)
939                 .finish(),
940             CodeSectionEntry(_) => f.debug_tuple("CodeSectionEntry").field(&"...").finish(),
941             ModuleSectionStart { count, range, size } => f
942                 .debug_struct("ModuleSectionStart")
943                 .field("count", count)
944                 .field("range", range)
945                 .field("size", size)
946                 .finish(),
947             ModuleSectionEntry { parser: _, range } => f
948                 .debug_struct("ModuleSectionEntry")
949                 .field("range", range)
950                 .finish(),
951             UnknownSection { id, range, .. } => f
952                 .debug_struct("UnknownSection")
953                 .field("id", id)
954                 .field("range", range)
955                 .finish(),
956             End => f.write_str("End"),
957         }
958     }
959 }
960 
clear_hint(mut err: BinaryReaderError) -> BinaryReaderError961 fn clear_hint(mut err: BinaryReaderError) -> BinaryReaderError {
962     err.inner.needed_hint = None;
963     err
964 }
965 
966 #[cfg(test)]
967 mod tests {
968     use super::*;
969 
970     macro_rules! assert_matches {
971         ($a:expr, $b:pat $(,)?) => {
972             match $a {
973                 $b => {}
974                 a => panic!("`{:?}` doesn't match `{}`", a, stringify!($b)),
975             }
976         };
977     }
978 
979     #[test]
header()980     fn header() {
981         assert!(Parser::default().parse(&[], true).is_err());
982         assert_matches!(
983             Parser::default().parse(&[], false),
984             Ok(Chunk::NeedMoreData(4)),
985         );
986         assert_matches!(
987             Parser::default().parse(b"\0", false),
988             Ok(Chunk::NeedMoreData(3)),
989         );
990         assert_matches!(
991             Parser::default().parse(b"\0asm", false),
992             Ok(Chunk::NeedMoreData(4)),
993         );
994         assert_matches!(
995             Parser::default().parse(b"\0asm\x01\0\0\0", false),
996             Ok(Chunk::Parsed {
997                 consumed: 8,
998                 payload: Payload::Version { num: 1, .. },
999             }),
1000         );
1001     }
1002 
parser_after_header() -> Parser1003     fn parser_after_header() -> Parser {
1004         let mut p = Parser::default();
1005         assert_matches!(
1006             p.parse(b"\0asm\x01\0\0\0", false),
1007             Ok(Chunk::Parsed {
1008                 consumed: 8,
1009                 payload: Payload::Version { num: 1, .. },
1010             }),
1011         );
1012         return p;
1013     }
1014 
1015     #[test]
start_section()1016     fn start_section() {
1017         assert_matches!(
1018             parser_after_header().parse(&[], false),
1019             Ok(Chunk::NeedMoreData(1)),
1020         );
1021         assert!(parser_after_header().parse(&[8], true).is_err());
1022         assert!(parser_after_header().parse(&[8, 1], true).is_err());
1023         assert!(parser_after_header().parse(&[8, 2], true).is_err());
1024         assert_matches!(
1025             parser_after_header().parse(&[8], false),
1026             Ok(Chunk::NeedMoreData(1)),
1027         );
1028         assert_matches!(
1029             parser_after_header().parse(&[8, 1], false),
1030             Ok(Chunk::NeedMoreData(1)),
1031         );
1032         assert_matches!(
1033             parser_after_header().parse(&[8, 2], false),
1034             Ok(Chunk::NeedMoreData(2)),
1035         );
1036         assert_matches!(
1037             parser_after_header().parse(&[8, 1, 1], false),
1038             Ok(Chunk::Parsed {
1039                 consumed: 3,
1040                 payload: Payload::StartSection { func: 1, .. },
1041             }),
1042         );
1043         assert!(parser_after_header().parse(&[8, 2, 1, 1], false).is_err());
1044         assert!(parser_after_header().parse(&[8, 0], false).is_err());
1045     }
1046 
1047     #[test]
end_works()1048     fn end_works() {
1049         assert_matches!(
1050             parser_after_header().parse(&[], true),
1051             Ok(Chunk::Parsed {
1052                 consumed: 0,
1053                 payload: Payload::End,
1054             }),
1055         );
1056     }
1057 
1058     #[test]
type_section()1059     fn type_section() {
1060         assert!(parser_after_header().parse(&[1], true).is_err());
1061         assert!(parser_after_header().parse(&[1, 0], false).is_err());
1062         // assert!(parser_after_header().parse(&[8, 2], true).is_err());
1063         assert_matches!(
1064             parser_after_header().parse(&[1], false),
1065             Ok(Chunk::NeedMoreData(1)),
1066         );
1067         assert_matches!(
1068             parser_after_header().parse(&[1, 1], false),
1069             Ok(Chunk::NeedMoreData(1)),
1070         );
1071         assert_matches!(
1072             parser_after_header().parse(&[1, 1, 1], false),
1073             Ok(Chunk::Parsed {
1074                 consumed: 3,
1075                 payload: Payload::TypeSection(_),
1076             }),
1077         );
1078         assert_matches!(
1079             parser_after_header().parse(&[1, 1, 1, 2, 3, 4], false),
1080             Ok(Chunk::Parsed {
1081                 consumed: 3,
1082                 payload: Payload::TypeSection(_),
1083             }),
1084         );
1085     }
1086 
1087     #[test]
custom_section()1088     fn custom_section() {
1089         assert!(parser_after_header().parse(&[0], true).is_err());
1090         assert!(parser_after_header().parse(&[0, 0], false).is_err());
1091         assert!(parser_after_header().parse(&[0, 1, 1], false).is_err());
1092         assert_matches!(
1093             parser_after_header().parse(&[0, 2, 1], false),
1094             Ok(Chunk::NeedMoreData(1)),
1095         );
1096         assert_matches!(
1097             parser_after_header().parse(&[0, 1, 0], false),
1098             Ok(Chunk::Parsed {
1099                 consumed: 3,
1100                 payload: Payload::CustomSection {
1101                     name: "",
1102                     data_offset: 11,
1103                     data: b"",
1104                     range: Range { start: 10, end: 11 },
1105                 },
1106             }),
1107         );
1108         assert_matches!(
1109             parser_after_header().parse(&[0, 2, 1, b'a'], false),
1110             Ok(Chunk::Parsed {
1111                 consumed: 4,
1112                 payload: Payload::CustomSection {
1113                     name: "a",
1114                     data_offset: 12,
1115                     data: b"",
1116                     range: Range { start: 10, end: 12 },
1117                 },
1118             }),
1119         );
1120         assert_matches!(
1121             parser_after_header().parse(&[0, 2, 0, b'a'], false),
1122             Ok(Chunk::Parsed {
1123                 consumed: 4,
1124                 payload: Payload::CustomSection {
1125                     name: "",
1126                     data_offset: 11,
1127                     data: b"a",
1128                     range: Range { start: 10, end: 12 },
1129                 },
1130             }),
1131         );
1132     }
1133 
1134     #[test]
function_section()1135     fn function_section() {
1136         assert!(parser_after_header().parse(&[10], true).is_err());
1137         assert!(parser_after_header().parse(&[10, 0], true).is_err());
1138         assert!(parser_after_header().parse(&[10, 1], true).is_err());
1139         assert_matches!(
1140             parser_after_header().parse(&[10], false),
1141             Ok(Chunk::NeedMoreData(1))
1142         );
1143         assert_matches!(
1144             parser_after_header().parse(&[10, 1], false),
1145             Ok(Chunk::NeedMoreData(1))
1146         );
1147         let mut p = parser_after_header();
1148         assert_matches!(
1149             p.parse(&[10, 1, 0], false),
1150             Ok(Chunk::Parsed {
1151                 consumed: 3,
1152                 payload: Payload::CodeSectionStart { count: 0, .. },
1153             }),
1154         );
1155         assert_matches!(
1156             p.parse(&[], true),
1157             Ok(Chunk::Parsed {
1158                 consumed: 0,
1159                 payload: Payload::End,
1160             }),
1161         );
1162         let mut p = parser_after_header();
1163         assert_matches!(
1164             p.parse(&[10, 2, 1, 0], false),
1165             Ok(Chunk::Parsed {
1166                 consumed: 3,
1167                 payload: Payload::CodeSectionStart { count: 1, .. },
1168             }),
1169         );
1170         assert_matches!(
1171             p.parse(&[0], false),
1172             Ok(Chunk::Parsed {
1173                 consumed: 1,
1174                 payload: Payload::CodeSectionEntry(_),
1175             }),
1176         );
1177         assert_matches!(
1178             p.parse(&[], true),
1179             Ok(Chunk::Parsed {
1180                 consumed: 0,
1181                 payload: Payload::End,
1182             }),
1183         );
1184 
1185         // 1 byte section with 1 function can't read the function body because
1186         // the section is too small
1187         let mut p = parser_after_header();
1188         assert_matches!(
1189             p.parse(&[10, 1, 1], false),
1190             Ok(Chunk::Parsed {
1191                 consumed: 3,
1192                 payload: Payload::CodeSectionStart { count: 1, .. },
1193             }),
1194         );
1195         assert_eq!(
1196             p.parse(&[0], false).unwrap_err().message(),
1197             "Unexpected EOF"
1198         );
1199 
1200         // section with 2 functions but section is cut off
1201         let mut p = parser_after_header();
1202         assert_matches!(
1203             p.parse(&[10, 2, 2], false),
1204             Ok(Chunk::Parsed {
1205                 consumed: 3,
1206                 payload: Payload::CodeSectionStart { count: 2, .. },
1207             }),
1208         );
1209         assert_matches!(
1210             p.parse(&[0], false),
1211             Ok(Chunk::Parsed {
1212                 consumed: 1,
1213                 payload: Payload::CodeSectionEntry(_),
1214             }),
1215         );
1216         assert_matches!(p.parse(&[], false), Ok(Chunk::NeedMoreData(1)));
1217         assert_eq!(
1218             p.parse(&[0], false).unwrap_err().message(),
1219             "Unexpected EOF",
1220         );
1221 
1222         // trailing data is bad
1223         let mut p = parser_after_header();
1224         assert_matches!(
1225             p.parse(&[10, 3, 1], false),
1226             Ok(Chunk::Parsed {
1227                 consumed: 3,
1228                 payload: Payload::CodeSectionStart { count: 1, .. },
1229             }),
1230         );
1231         assert_matches!(
1232             p.parse(&[0], false),
1233             Ok(Chunk::Parsed {
1234                 consumed: 1,
1235                 payload: Payload::CodeSectionEntry(_),
1236             }),
1237         );
1238         assert_eq!(
1239             p.parse(&[0], false).unwrap_err().message(),
1240             "trailing bytes at end of section",
1241         );
1242     }
1243 
1244     #[test]
module_code_errors()1245     fn module_code_errors() {
1246         // no bytes to say size of section
1247         assert!(parser_after_header().parse(&[14], true).is_err());
1248         // section must start with a u32
1249         assert!(parser_after_header().parse(&[14, 0], true).is_err());
1250         // EOF before we finish reading the section
1251         assert!(parser_after_header().parse(&[14, 1], true).is_err());
1252     }
1253 
1254     #[test]
module_code_one()1255     fn module_code_one() {
1256         let mut p = parser_after_header();
1257         assert_matches!(p.parse(&[14], false), Ok(Chunk::NeedMoreData(1)));
1258         assert_matches!(p.parse(&[14, 9], false), Ok(Chunk::NeedMoreData(1)));
1259         // Module code section, 10 bytes large, one module.
1260         assert_matches!(
1261             p.parse(&[14, 10, 1], false),
1262             Ok(Chunk::Parsed {
1263                 consumed: 3,
1264                 payload: Payload::ModuleSectionStart { count: 1, .. },
1265             })
1266         );
1267         // Declare an empty module, which will be 8 bytes large for the header.
1268         // Switch to the sub-parser on success.
1269         let mut sub = match p.parse(&[8], false) {
1270             Ok(Chunk::Parsed {
1271                 consumed: 1,
1272                 payload: Payload::ModuleSectionEntry { parser, .. },
1273             }) => parser,
1274             other => panic!("bad parse {:?}", other),
1275         };
1276 
1277         // Parse the header of the submodule with the sub-parser.
1278         assert_matches!(sub.parse(&[], false), Ok(Chunk::NeedMoreData(4)));
1279         assert_matches!(sub.parse(b"\0asm", false), Ok(Chunk::NeedMoreData(4)));
1280         assert_matches!(
1281             sub.parse(b"\0asm\x01\0\0\0", false),
1282             Ok(Chunk::Parsed {
1283                 consumed: 8,
1284                 payload: Payload::Version { num: 1, .. },
1285             }),
1286         );
1287 
1288         // The sub-parser should be byte-limited so the next byte shouldn't get
1289         // consumed, it's intended for the parent parser.
1290         assert_matches!(
1291             sub.parse(&[10], false),
1292             Ok(Chunk::Parsed {
1293                 consumed: 0,
1294                 payload: Payload::End,
1295             }),
1296         );
1297 
1298         // The parent parser should now be back to resuming, and we simulate it
1299         // being done with bytes to ensure that it's safely at the end,
1300         // completing the module code section.
1301         assert_matches!(p.parse(&[], false), Ok(Chunk::NeedMoreData(1)));
1302         assert_matches!(
1303             p.parse(&[], true),
1304             Ok(Chunk::Parsed {
1305                 consumed: 0,
1306                 payload: Payload::End,
1307             }),
1308         );
1309     }
1310 
1311     #[test]
nested_section_too_big()1312     fn nested_section_too_big() {
1313         let mut p = parser_after_header();
1314         // Module code section, 12 bytes large, one module. This leaves 11 bytes
1315         // of payload for the module definition itself.
1316         assert_matches!(
1317             p.parse(&[14, 12, 1], false),
1318             Ok(Chunk::Parsed {
1319                 consumed: 3,
1320                 payload: Payload::ModuleSectionStart { count: 1, .. },
1321             })
1322         );
1323         // Use one byte to say we're a 10 byte module, which fits exactly within
1324         // our module code section.
1325         let mut sub = match p.parse(&[10], false) {
1326             Ok(Chunk::Parsed {
1327                 consumed: 1,
1328                 payload: Payload::ModuleSectionEntry { parser, .. },
1329             }) => parser,
1330             other => panic!("bad parse {:?}", other),
1331         };
1332 
1333         // use 8 bytes to parse the header, leaving 2 remaining bytes in our
1334         // module.
1335         assert_matches!(
1336             sub.parse(b"\0asm\x01\0\0\0", false),
1337             Ok(Chunk::Parsed {
1338                 consumed: 8,
1339                 payload: Payload::Version { num: 1, .. },
1340             }),
1341         );
1342 
1343         // We can't parse a section which declares its bigger than the outer
1344         // module. This is section 1, one byte big, with one content byte. The
1345         // content byte, however, lives outside of the parent's module code
1346         // section.
1347         assert_eq!(
1348             sub.parse(&[1, 1, 0], false).unwrap_err().message(),
1349             "section too large",
1350         );
1351     }
1352 }
1353