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 super::{
17     BinaryReader, BinaryReaderError, OperatorsReader, Range, Result, SectionIteratorLimited,
18     SectionReader, SectionWithLimitedItems, Type,
19 };
20 
21 #[derive(Debug, Clone)]
22 pub struct FunctionBody<'a> {
23     offset: usize,
24     data: &'a [u8],
25 }
26 
27 impl<'a> FunctionBody<'a> {
new(offset: usize, data: &'a [u8]) -> Self28     pub fn new(offset: usize, data: &'a [u8]) -> Self {
29         Self { offset, data }
30     }
31 
get_binary_reader<'b>(&self) -> BinaryReader<'b> where 'a: 'b,32     pub fn get_binary_reader<'b>(&self) -> BinaryReader<'b>
33     where
34         'a: 'b,
35     {
36         BinaryReader::new_with_offset(self.data, self.offset)
37     }
38 
skip_locals(reader: &mut BinaryReader) -> Result<()>39     fn skip_locals(reader: &mut BinaryReader) -> Result<()> {
40         let count = reader.read_var_u32()?;
41         for _ in 0..count {
42             reader.skip_var_32()?;
43             reader.skip_type()?;
44         }
45         Ok(())
46     }
47 
get_locals_reader<'b>(&self) -> Result<LocalsReader<'b>> where 'a: 'b,48     pub fn get_locals_reader<'b>(&self) -> Result<LocalsReader<'b>>
49     where
50         'a: 'b,
51     {
52         let mut reader = BinaryReader::new_with_offset(self.data, self.offset);
53         let count = reader.read_var_u32()?;
54         Ok(LocalsReader { reader, count })
55     }
56 
get_operators_reader<'b>(&self) -> Result<OperatorsReader<'b>> where 'a: 'b,57     pub fn get_operators_reader<'b>(&self) -> Result<OperatorsReader<'b>>
58     where
59         'a: 'b,
60     {
61         let mut reader = BinaryReader::new_with_offset(self.data, self.offset);
62         Self::skip_locals(&mut reader)?;
63         let pos = reader.position;
64         Ok(OperatorsReader::new(&self.data[pos..], self.offset + pos))
65     }
66 
range(&self) -> Range67     pub fn range(&self) -> Range {
68         Range {
69             start: self.offset,
70             end: self.offset + self.data.len(),
71         }
72     }
73 }
74 
75 pub struct LocalsReader<'a> {
76     reader: BinaryReader<'a>,
77     count: u32,
78 }
79 
80 impl<'a> LocalsReader<'a> {
get_count(&self) -> u3281     pub fn get_count(&self) -> u32 {
82         self.count
83     }
84 
original_position(&self) -> usize85     pub fn original_position(&self) -> usize {
86         self.reader.original_position()
87     }
88 
read(&mut self) -> Result<(u32, Type)>89     pub fn read(&mut self) -> Result<(u32, Type)> {
90         let count = self.reader.read_var_u32()?;
91         let value_type = self.reader.read_type()?;
92         Ok((count, value_type))
93     }
94 }
95 
96 pub struct CodeSectionReader<'a> {
97     reader: BinaryReader<'a>,
98     count: u32,
99 }
100 
101 impl<'a> IntoIterator for LocalsReader<'a> {
102     type Item = Result<(u32, Type)>;
103     type IntoIter = LocalsIterator<'a>;
into_iter(self) -> Self::IntoIter104     fn into_iter(self) -> Self::IntoIter {
105         let count = self.count;
106         LocalsIterator {
107             reader: self,
108             left: count,
109             err: false,
110         }
111     }
112 }
113 
114 pub struct LocalsIterator<'a> {
115     reader: LocalsReader<'a>,
116     left: u32,
117     err: bool,
118 }
119 
120 impl<'a> Iterator for LocalsIterator<'a> {
121     type Item = Result<(u32, Type)>;
next(&mut self) -> Option<Self::Item>122     fn next(&mut self) -> Option<Self::Item> {
123         if self.err || self.left == 0 {
124             return None;
125         }
126         let result = self.reader.read();
127         self.err = result.is_err();
128         self.left -= 1;
129         Some(result)
130     }
size_hint(&self) -> (usize, Option<usize>)131     fn size_hint(&self) -> (usize, Option<usize>) {
132         let count = self.reader.get_count() as usize;
133         (count, Some(count))
134     }
135 }
136 
137 impl<'a> CodeSectionReader<'a> {
new(data: &'a [u8], offset: usize) -> Result<CodeSectionReader<'a>>138     pub fn new(data: &'a [u8], offset: usize) -> Result<CodeSectionReader<'a>> {
139         let mut reader = BinaryReader::new_with_offset(data, offset);
140         let count = reader.read_var_u32()?;
141         Ok(CodeSectionReader { reader, count })
142     }
143 
original_position(&self) -> usize144     pub fn original_position(&self) -> usize {
145         self.reader.original_position()
146     }
147 
get_count(&self) -> u32148     pub fn get_count(&self) -> u32 {
149         self.count
150     }
151 
verify_body_end(&self, end: usize) -> Result<()>152     fn verify_body_end(&self, end: usize) -> Result<()> {
153         if self.reader.buffer.len() < end {
154             return Err(BinaryReaderError::new(
155                 "Function body extends past end of the code section",
156                 self.reader.original_offset + self.reader.buffer.len(),
157             ));
158         }
159         Ok(())
160     }
161 
162     /// Reads content of the code section.
163     ///
164     /// # Examples
165     /// ```
166     /// use wasmparser::CodeSectionReader;
167     /// # let data: &[u8] = &[
168     /// #     0x01, 0x03, 0x00, 0x01, 0x0b];
169     /// let mut code_reader = CodeSectionReader::new(data, 0).unwrap();
170     /// for _ in 0..code_reader.get_count() {
171     ///     let body = code_reader.read().expect("function body");
172     ///     let mut binary_reader = body.get_binary_reader();
173     ///     assert!(binary_reader.read_var_u32().expect("local count") == 0);
174     ///     let op = binary_reader.read_operator().expect("first operator");
175     ///     println!("First operator: {:?}", op);
176     /// }
177     /// ```
read<'b>(&mut self) -> Result<FunctionBody<'b>> where 'a: 'b,178     pub fn read<'b>(&mut self) -> Result<FunctionBody<'b>>
179     where
180         'a: 'b,
181     {
182         let size = self.reader.read_var_u32()? as usize;
183         let body_start = self.reader.position;
184         let body_end = body_start + size;
185         self.verify_body_end(body_end)?;
186         self.reader.skip_to(body_end);
187         Ok(FunctionBody {
188             offset: self.reader.original_offset + body_start,
189             data: &self.reader.buffer[body_start..body_end],
190         })
191     }
192 }
193 
194 impl<'a> SectionReader for CodeSectionReader<'a> {
195     type Item = FunctionBody<'a>;
read(&mut self) -> Result<Self::Item>196     fn read(&mut self) -> Result<Self::Item> {
197         CodeSectionReader::read(self)
198     }
eof(&self) -> bool199     fn eof(&self) -> bool {
200         self.reader.eof()
201     }
original_position(&self) -> usize202     fn original_position(&self) -> usize {
203         CodeSectionReader::original_position(self)
204     }
range(&self) -> Range205     fn range(&self) -> Range {
206         self.reader.range()
207     }
208 }
209 
210 impl<'a> SectionWithLimitedItems for CodeSectionReader<'a> {
get_count(&self) -> u32211     fn get_count(&self) -> u32 {
212         CodeSectionReader::get_count(self)
213     }
214 }
215 
216 impl<'a> IntoIterator for CodeSectionReader<'a> {
217     type Item = Result<FunctionBody<'a>>;
218     type IntoIter = SectionIteratorLimited<CodeSectionReader<'a>>;
219 
220     /// Implements iterator over the code section.
221     ///
222     /// # Examples
223     /// ```
224     /// use wasmparser::CodeSectionReader;
225     /// # let data: &[u8] = &[
226     /// #     0x01, 0x03, 0x00, 0x01, 0x0b];
227     /// let mut code_reader = CodeSectionReader::new(data, 0).unwrap();
228     /// for body in code_reader {
229     ///     let mut binary_reader = body.expect("b").get_binary_reader();
230     ///     assert!(binary_reader.read_var_u32().expect("local count") == 0);
231     ///     let op = binary_reader.read_operator().expect("first operator");
232     ///     println!("First operator: {:?}", op);
233     /// }
234     /// ```
into_iter(self) -> Self::IntoIter235     fn into_iter(self) -> Self::IntoIter {
236         SectionIteratorLimited::new(self)
237     }
238 }
239