1 /* Copyright 2018 Mozilla Foundation
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 use core::iter::{IntoIterator, Iterator};
17 
18 use super::{
19     BinaryReader, BinaryReaderError, CustomSectionKind, Range, Result, SectionCode, SectionHeader,
20 };
21 
22 use super::{
23     read_data_count_section_content, read_sourcemappingurl_section_content,
24     read_start_section_content, CodeSectionReader, DataSectionReader, ElementSectionReader,
25     ExportSectionReader, FunctionSectionReader, GlobalSectionReader, ImportSectionReader,
26     LinkingSectionReader, MemorySectionReader, NameSectionReader, ProducersSectionReader,
27     RelocSectionReader, TableSectionReader, TypeSectionReader,
28 };
29 
30 #[derive(Debug)]
31 pub struct Section<'a> {
32     pub code: SectionCode<'a>,
33     offset: usize,
34     data: &'a [u8],
35 }
36 
37 impl<'a> Section<'a> {
38     /// Creates reader for the type section. Available when the reader just read
39     /// the type section.
get_type_section_reader<'b>(&self) -> Result<TypeSectionReader<'b>> where 'a: 'b,40     pub fn get_type_section_reader<'b>(&self) -> Result<TypeSectionReader<'b>>
41     where
42         'a: 'b,
43     {
44         match self.code {
45             SectionCode::Type => TypeSectionReader::new(self.data, self.offset),
46             _ => panic!("Invalid state for get_type_section_reader"),
47         }
48     }
49 
50     /// Creates reader for the function section. Available when the reader just read
51     /// the function section.
get_function_section_reader<'b>(&self) -> Result<FunctionSectionReader<'b>> where 'a: 'b,52     pub fn get_function_section_reader<'b>(&self) -> Result<FunctionSectionReader<'b>>
53     where
54         'a: 'b,
55     {
56         match self.code {
57             SectionCode::Function => FunctionSectionReader::new(self.data, self.offset),
58             _ => panic!("Invalid state for get_function_section_reader"),
59         }
60     }
61 
62     /// Creates reader for the code section. Available when the reader just read
63     /// the code section.
get_code_section_reader<'b>(&self) -> Result<CodeSectionReader<'b>> where 'a: 'b,64     pub fn get_code_section_reader<'b>(&self) -> Result<CodeSectionReader<'b>>
65     where
66         'a: 'b,
67     {
68         match self.code {
69             SectionCode::Code => CodeSectionReader::new(self.data, self.offset),
70             _ => panic!("Invalid state for get_function_section_reader"),
71         }
72     }
73 
74     /// Creates reader for the export section. Available when the reader just read
75     /// the export section.
get_export_section_reader<'b>(&self) -> Result<ExportSectionReader<'b>> where 'a: 'b,76     pub fn get_export_section_reader<'b>(&self) -> Result<ExportSectionReader<'b>>
77     where
78         'a: 'b,
79     {
80         match self.code {
81             SectionCode::Export => ExportSectionReader::new(self.data, self.offset),
82             _ => panic!("Invalid state for get_export_section_reader"),
83         }
84     }
85 
86     /// Creates reader for the import section. Available when the reader just read
87     /// the import section.
get_import_section_reader<'b>(&self) -> Result<ImportSectionReader<'b>> where 'a: 'b,88     pub fn get_import_section_reader<'b>(&self) -> Result<ImportSectionReader<'b>>
89     where
90         'a: 'b,
91     {
92         match self.code {
93             SectionCode::Import => ImportSectionReader::new(self.data, self.offset),
94             _ => panic!("Invalid state for get_import_section_reader"),
95         }
96     }
97 
98     /// Creates reader for the global section. Available when the reader just read
99     /// the global section.
get_global_section_reader<'b>(&self) -> Result<GlobalSectionReader<'b>> where 'a: 'b,100     pub fn get_global_section_reader<'b>(&self) -> Result<GlobalSectionReader<'b>>
101     where
102         'a: 'b,
103     {
104         match self.code {
105             SectionCode::Global => GlobalSectionReader::new(self.data, self.offset),
106             _ => panic!("Invalid state for get_global_section_reader"),
107         }
108     }
109 
110     /// Creates reader for the memory section. Available when the reader just read
111     /// the memory section.
get_memory_section_reader<'b>(&self) -> Result<MemorySectionReader<'b>> where 'a: 'b,112     pub fn get_memory_section_reader<'b>(&self) -> Result<MemorySectionReader<'b>>
113     where
114         'a: 'b,
115     {
116         match self.code {
117             SectionCode::Memory => MemorySectionReader::new(self.data, self.offset),
118             _ => panic!("Invalid state for get_memory_section_reader"),
119         }
120     }
121 
122     /// Creates reader for the data section. Available when the reader just read
123     /// the data section.
get_data_section_reader<'b>(&self) -> Result<DataSectionReader<'b>> where 'a: 'b,124     pub fn get_data_section_reader<'b>(&self) -> Result<DataSectionReader<'b>>
125     where
126         'a: 'b,
127     {
128         match self.code {
129             SectionCode::Data => DataSectionReader::new(self.data, self.offset),
130             _ => panic!("Invalid state for get_data_section_reader"),
131         }
132     }
133 
134     /// Creates reader for the table section. Available when the reader just read
135     /// the table section.
get_table_section_reader<'b>(&self) -> Result<TableSectionReader<'b>> where 'a: 'b,136     pub fn get_table_section_reader<'b>(&self) -> Result<TableSectionReader<'b>>
137     where
138         'a: 'b,
139     {
140         match self.code {
141             SectionCode::Table => TableSectionReader::new(self.data, self.offset),
142             _ => panic!("Invalid state for get_table_section_reader"),
143         }
144     }
145 
146     /// Creates reader for the element section. Available when the reader just read
147     /// the element section.
get_element_section_reader<'b>(&self) -> Result<ElementSectionReader<'b>> where 'a: 'b,148     pub fn get_element_section_reader<'b>(&self) -> Result<ElementSectionReader<'b>>
149     where
150         'a: 'b,
151     {
152         match self.code {
153             SectionCode::Element => ElementSectionReader::new(self.data, self.offset),
154             _ => panic!("Invalid state for get_element_section_reader"),
155         }
156     }
157 
get_name_section_reader<'b>(&self) -> Result<NameSectionReader<'b>> where 'a: 'b,158     pub fn get_name_section_reader<'b>(&self) -> Result<NameSectionReader<'b>>
159     where
160         'a: 'b,
161     {
162         match self.code {
163             SectionCode::Custom {
164                 kind: CustomSectionKind::Name,
165                 ..
166             } => NameSectionReader::new(self.data, self.offset),
167             _ => panic!("Invalid state for get_name_section_reader"),
168         }
169     }
170 
get_producers_section_reader<'b>(&self) -> Result<ProducersSectionReader<'b>> where 'a: 'b,171     pub fn get_producers_section_reader<'b>(&self) -> Result<ProducersSectionReader<'b>>
172     where
173         'a: 'b,
174     {
175         match self.code {
176             SectionCode::Custom {
177                 kind: CustomSectionKind::Producers,
178                 ..
179             } => ProducersSectionReader::new(self.data, self.offset),
180             _ => panic!("Invalid state for get_producers_section_reader"),
181         }
182     }
183 
get_linking_section_reader<'b>(&self) -> Result<LinkingSectionReader<'b>> where 'a: 'b,184     pub fn get_linking_section_reader<'b>(&self) -> Result<LinkingSectionReader<'b>>
185     where
186         'a: 'b,
187     {
188         match self.code {
189             SectionCode::Custom {
190                 kind: CustomSectionKind::Linking,
191                 ..
192             } => LinkingSectionReader::new(self.data, self.offset),
193             _ => panic!("Invalid state for get_linking_section_reader"),
194         }
195     }
196 
get_reloc_section_reader<'b>(&self) -> Result<RelocSectionReader<'b>> where 'a: 'b,197     pub fn get_reloc_section_reader<'b>(&self) -> Result<RelocSectionReader<'b>>
198     where
199         'a: 'b,
200     {
201         match self.code {
202             SectionCode::Custom {
203                 kind: CustomSectionKind::Reloc,
204                 ..
205             } => RelocSectionReader::new(self.data, self.offset),
206             _ => panic!("Invalid state for get_reloc_section_reader"),
207         }
208     }
209 
get_start_section_content(&self) -> Result<u32>210     pub fn get_start_section_content(&self) -> Result<u32> {
211         match self.code {
212             SectionCode::Start => read_start_section_content(self.data, self.offset),
213             _ => panic!("Invalid state for get_start_section_content"),
214         }
215     }
216 
get_data_count_section_content(&self) -> Result<u32>217     pub fn get_data_count_section_content(&self) -> Result<u32> {
218         match self.code {
219             SectionCode::DataCount => read_data_count_section_content(self.data, self.offset),
220             _ => panic!("Invalid state for get_data_count_section_content"),
221         }
222     }
223 
get_sourcemappingurl_section_content<'b>(&self) -> Result<&'b str> where 'a: 'b,224     pub fn get_sourcemappingurl_section_content<'b>(&self) -> Result<&'b str>
225     where
226         'a: 'b,
227     {
228         match self.code {
229             SectionCode::Custom {
230                 kind: CustomSectionKind::SourceMappingURL,
231                 ..
232             } => read_sourcemappingurl_section_content(self.data, self.offset),
233             _ => panic!("Invalid state for get_start_section_content"),
234         }
235     }
236 
get_binary_reader<'b>(&self) -> BinaryReader<'b> where 'a: 'b,237     pub fn get_binary_reader<'b>(&self) -> BinaryReader<'b>
238     where
239         'a: 'b,
240     {
241         BinaryReader::new_with_offset(self.data, self.offset)
242     }
243 
range(&self) -> Range244     pub fn range(&self) -> Range {
245         Range {
246             start: self.offset,
247             end: self.offset + self.data.len(),
248         }
249     }
250 
content<'b>(&self) -> Result<SectionContent<'b>> where 'a: 'b,251     pub fn content<'b>(&self) -> Result<SectionContent<'b>>
252     where
253         'a: 'b,
254     {
255         let c = match self.code {
256             SectionCode::Type => SectionContent::Type(self.get_type_section_reader()?),
257             SectionCode::Function => SectionContent::Function(self.get_function_section_reader()?),
258             SectionCode::Code => SectionContent::Code(self.get_code_section_reader()?),
259             SectionCode::Export => SectionContent::Export(self.get_export_section_reader()?),
260             SectionCode::Import => SectionContent::Import(self.get_import_section_reader()?),
261             SectionCode::Global => SectionContent::Global(self.get_global_section_reader()?),
262             SectionCode::Memory => SectionContent::Memory(self.get_memory_section_reader()?),
263             SectionCode::Data => SectionContent::Data(self.get_data_section_reader()?),
264             SectionCode::Table => SectionContent::Table(self.get_table_section_reader()?),
265             SectionCode::Element => SectionContent::Element(self.get_element_section_reader()?),
266             SectionCode::Start => SectionContent::Start(self.get_start_section_content()?),
267             SectionCode::DataCount => {
268                 SectionContent::DataCount(self.get_data_count_section_content()?)
269             }
270             SectionCode::Custom { kind, name } => {
271                 let binary = self.get_binary_reader();
272                 let content = match kind {
273                     CustomSectionKind::Name => {
274                         Some(CustomSectionContent::Name(self.get_name_section_reader()?))
275                     }
276                     CustomSectionKind::Producers => Some(CustomSectionContent::Producers(
277                         self.get_producers_section_reader()?,
278                     )),
279                     CustomSectionKind::Linking => Some(CustomSectionContent::Linking(
280                         self.get_linking_section_reader()?,
281                     )),
282                     CustomSectionKind::Reloc => Some(CustomSectionContent::Reloc(
283                         self.get_reloc_section_reader()?,
284                     )),
285                     CustomSectionKind::SourceMappingURL => {
286                         Some(CustomSectionContent::SourceMappingURL(
287                             self.get_sourcemappingurl_section_content()?,
288                         ))
289                     }
290 
291                     _ => None,
292                 };
293                 SectionContent::Custom {
294                     name,
295                     binary,
296                     content,
297                 }
298             }
299         };
300         Ok(c)
301     }
302 }
303 
304 pub enum SectionContent<'a> {
305     Type(TypeSectionReader<'a>),
306     Function(FunctionSectionReader<'a>),
307     Code(CodeSectionReader<'a>),
308     Export(ExportSectionReader<'a>),
309     Import(ImportSectionReader<'a>),
310     Global(GlobalSectionReader<'a>),
311     Memory(MemorySectionReader<'a>),
312     Data(DataSectionReader<'a>),
313     Table(TableSectionReader<'a>),
314     Element(ElementSectionReader<'a>),
315     Start(u32),
316     DataCount(u32),
317     Custom {
318         name: &'a str,
319         binary: BinaryReader<'a>,
320         content: Option<CustomSectionContent<'a>>,
321     },
322 }
323 
324 pub enum CustomSectionContent<'a> {
325     Name(NameSectionReader<'a>),
326     Producers(ProducersSectionReader<'a>),
327     Linking(LinkingSectionReader<'a>),
328     Reloc(RelocSectionReader<'a>),
329     SourceMappingURL(&'a str),
330 }
331 
332 /// Reads top-level WebAssembly file structure: header and sections.
333 pub struct ModuleReader<'a> {
334     reader: BinaryReader<'a>,
335     version: u32,
336     read_ahead: Option<(usize, SectionHeader<'a>)>,
337 }
338 
339 impl<'a> ModuleReader<'a> {
new(data: &[u8]) -> Result<ModuleReader>340     pub fn new(data: &[u8]) -> Result<ModuleReader> {
341         let mut reader = BinaryReader::new(data);
342         let version = reader.read_file_header()?;
343         Ok(ModuleReader {
344             reader,
345             version,
346             read_ahead: None,
347         })
348     }
349 
get_version(&self) -> u32350     pub fn get_version(&self) -> u32 {
351         self.version
352     }
353 
current_position(&self) -> usize354     pub fn current_position(&self) -> usize {
355         match self.read_ahead {
356             Some((position, _)) => position,
357             _ => self.reader.current_position(),
358         }
359     }
360 
eof(&self) -> bool361     pub fn eof(&self) -> bool {
362         self.read_ahead.is_none() && self.reader.eof()
363     }
364 
verify_section_end(&self, end: usize) -> Result<()>365     fn verify_section_end(&self, end: usize) -> Result<()> {
366         if self.reader.buffer.len() < end {
367             return Err(BinaryReaderError {
368                 message: "Section body extends past end of file",
369                 offset: self.reader.buffer.len(),
370             });
371         }
372         if self.reader.position > end {
373             return Err(BinaryReaderError {
374                 message: "Section header is too big to fit into section body",
375                 offset: end,
376             });
377         }
378         Ok(())
379     }
380 
381     /// Reads next top-level record from the WebAssembly binary data.
382     /// The methods returns reference to current state of the reader.
383     ///
384     /// # Examples
385     /// ```
386     /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
387     /// #     0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
388     /// #     0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
389     /// use wasmparser::ModuleReader;
390     /// let mut reader = ModuleReader::new(data).expect("reader");
391     /// let section = reader.read().expect("section #1");
392     /// println!("First section {:?}", section);
393     /// let section = reader.read().expect("section #2");
394     /// println!("Second section {:?}", section);
395     /// assert!(!reader.eof(), "there are more sections");
396     /// ```
read<'b>(&mut self) -> Result<Section<'b>> where 'a: 'b,397     pub fn read<'b>(&mut self) -> Result<Section<'b>>
398     where
399         'a: 'b,
400     {
401         let SectionHeader {
402             code,
403             payload_start,
404             payload_len,
405         } = match self.read_ahead.take() {
406             Some((_, section_header)) => section_header,
407             None => self.reader.read_section_header()?,
408         };
409         let payload_end = payload_start + payload_len;
410         self.verify_section_end(payload_end)?;
411         let body_start = self.reader.position;
412         self.reader.skip_to(payload_end);
413         Ok(Section {
414             code,
415             offset: body_start,
416             data: &self.reader.buffer[body_start..payload_end],
417         })
418     }
419 
ensure_read_ahead(&mut self) -> Result<()>420     fn ensure_read_ahead(&mut self) -> Result<()> {
421         if self.read_ahead.is_none() && !self.eof() {
422             let position = self.reader.current_position();
423             self.read_ahead = Some((position, self.reader.read_section_header()?));
424         }
425         Ok(())
426     }
427 
428     /// Skips custom sections.
429     ///
430     /// # Examples
431     /// ```
432     /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
433     /// #     0x00, 0x8, 0x03, 0x63, 0x61, 0x74, 0x01, 0x02, 0x03, 0x04,
434     /// #     0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
435     /// #     0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
436     /// use wasmparser::ModuleReader;
437     /// use wasmparser::SectionCode;
438     /// let mut reader = ModuleReader::new(data).expect("reader");
439     /// while { reader.skip_custom_sections(); !reader.eof() } {
440     ///     let section = reader.read().expect("section");
441     ///     if let SectionCode::Custom {..} = section.code { panic!("no custom"); }
442     ///     println!("Section {:?}", section);
443     /// }
444     /// ```
skip_custom_sections(&mut self) -> Result<()>445     pub fn skip_custom_sections(&mut self) -> Result<()> {
446         loop {
447             self.ensure_read_ahead()?;
448             match self.read_ahead {
449                 Some((
450                     _,
451                     SectionHeader {
452                         code: SectionCode::Custom { .. },
453                         payload_start,
454                         payload_len,
455                     },
456                 )) => {
457                     self.verify_section_end(payload_start + payload_len)?;
458                     // Skip section
459                     self.read_ahead = None;
460                     self.reader.skip_to(payload_start + payload_len);
461                 }
462                 _ => break,
463             };
464         }
465         Ok(())
466     }
467 }
468 
469 impl<'a> IntoIterator for ModuleReader<'a> {
470     type Item = Result<Section<'a>>;
471     type IntoIter = ModuleIterator<'a>;
into_iter(self) -> Self::IntoIter472     fn into_iter(self) -> Self::IntoIter {
473         ModuleIterator {
474             reader: self,
475             err: false,
476         }
477     }
478 }
479 
480 pub struct ModuleIterator<'a> {
481     reader: ModuleReader<'a>,
482     err: bool,
483 }
484 
485 impl<'a> Iterator for ModuleIterator<'a> {
486     type Item = Result<Section<'a>>;
487 
488     /// Iterates sections from the WebAssembly binary data. Stops at first error.
489     ///
490     /// # Examples
491     /// ```
492     /// # let data: &[u8] = &[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00,
493     /// #     0x01, 0x4, 0x01, 0x60, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00,
494     /// #     0x0a, 0x05, 0x01, 0x03, 0x00, 0x01, 0x0b];
495     /// use wasmparser::ModuleReader;
496     /// for section in ModuleReader::new(data).expect("reader") {
497     ///     println!("Section {:?}", section);
498     /// }
499     /// ```
next(&mut self) -> Option<Self::Item>500     fn next(&mut self) -> Option<Self::Item> {
501         if self.err || self.reader.eof() {
502             return None;
503         }
504         let result = self.reader.read();
505         self.err = result.is_err();
506         Some(result)
507     }
508 }
509