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, InitExpr, Result, SectionIteratorLimited, SectionReader, 18 SectionWithLimitedItems, Type, 19 }; 20 use crate::{ExternalKind, Operator}; 21 22 #[derive(Clone)] 23 pub struct Element<'a> { 24 pub kind: ElementKind<'a>, 25 pub items: ElementItems<'a>, 26 pub ty: Type, 27 } 28 29 #[derive(Clone)] 30 pub enum ElementKind<'a> { 31 Passive, 32 Active { 33 table_index: u32, 34 init_expr: InitExpr<'a>, 35 }, 36 Declared, 37 } 38 39 #[derive(Debug, Copy, Clone)] 40 pub struct ElementItems<'a> { 41 exprs: bool, 42 offset: usize, 43 data: &'a [u8], 44 } 45 46 #[derive(Debug)] 47 pub enum ElementItem { 48 Null(Type), 49 Func(u32), 50 } 51 52 impl<'a> ElementItems<'a> { get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>> where 'a: 'b,53 pub fn get_items_reader<'b>(&self) -> Result<ElementItemsReader<'b>> 54 where 55 'a: 'b, 56 { 57 ElementItemsReader::new(self.data, self.offset, self.exprs) 58 } 59 } 60 61 pub struct ElementItemsReader<'a> { 62 reader: BinaryReader<'a>, 63 count: u32, 64 exprs: bool, 65 } 66 67 impl<'a> ElementItemsReader<'a> { new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader>68 pub fn new(data: &[u8], offset: usize, exprs: bool) -> Result<ElementItemsReader> { 69 let mut reader = BinaryReader::new_with_offset(data, offset); 70 let count = reader.read_var_u32()?; 71 Ok(ElementItemsReader { 72 reader, 73 count, 74 exprs, 75 }) 76 } 77 original_position(&self) -> usize78 pub fn original_position(&self) -> usize { 79 self.reader.original_position() 80 } 81 get_count(&self) -> u3282 pub fn get_count(&self) -> u32 { 83 self.count 84 } 85 uses_exprs(&self) -> bool86 pub fn uses_exprs(&self) -> bool { 87 self.exprs 88 } 89 read(&mut self) -> Result<ElementItem>90 pub fn read(&mut self) -> Result<ElementItem> { 91 if self.exprs { 92 let offset = self.reader.original_position(); 93 let ret = match self.reader.read_operator()? { 94 Operator::RefNull { ty } => ElementItem::Null(ty), 95 Operator::RefFunc { function_index } => ElementItem::Func(function_index), 96 _ => return Err(BinaryReaderError::new("invalid passive segment", offset)), 97 }; 98 match self.reader.read_operator()? { 99 Operator::End => {} 100 _ => return Err(BinaryReaderError::new("invalid passive segment", offset)), 101 } 102 Ok(ret) 103 } else { 104 self.reader.read_var_u32().map(ElementItem::Func) 105 } 106 } 107 } 108 109 impl<'a> IntoIterator for ElementItemsReader<'a> { 110 type Item = Result<ElementItem>; 111 type IntoIter = ElementItemsIterator<'a>; into_iter(self) -> Self::IntoIter112 fn into_iter(self) -> Self::IntoIter { 113 let count = self.count; 114 ElementItemsIterator { 115 reader: self, 116 left: count, 117 err: false, 118 } 119 } 120 } 121 122 pub struct ElementItemsIterator<'a> { 123 reader: ElementItemsReader<'a>, 124 left: u32, 125 err: bool, 126 } 127 128 impl<'a> Iterator for ElementItemsIterator<'a> { 129 type Item = Result<ElementItem>; next(&mut self) -> Option<Self::Item>130 fn next(&mut self) -> Option<Self::Item> { 131 if self.err || self.left == 0 { 132 return None; 133 } 134 let result = self.reader.read(); 135 self.err = result.is_err(); 136 self.left -= 1; 137 Some(result) 138 } size_hint(&self) -> (usize, Option<usize>)139 fn size_hint(&self) -> (usize, Option<usize>) { 140 let count = self.reader.get_count() as usize; 141 (count, Some(count)) 142 } 143 } 144 145 pub struct ElementSectionReader<'a> { 146 reader: BinaryReader<'a>, 147 count: u32, 148 } 149 150 impl<'a> ElementSectionReader<'a> { new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>>151 pub fn new(data: &'a [u8], offset: usize) -> Result<ElementSectionReader<'a>> { 152 let mut reader = BinaryReader::new_with_offset(data, offset); 153 let count = reader.read_var_u32()?; 154 Ok(ElementSectionReader { reader, count }) 155 } 156 original_position(&self) -> usize157 pub fn original_position(&self) -> usize { 158 self.reader.original_position() 159 } 160 get_count(&self) -> u32161 pub fn get_count(&self) -> u32 { 162 self.count 163 } 164 165 /// Reads content of the element section. 166 /// 167 /// # Examples 168 /// 169 /// ```no_run 170 /// # let data: &[u8] = &[]; 171 /// use wasmparser::{ModuleReader, ElementKind}; 172 /// use wasmparser::Result; 173 /// let mut reader = ModuleReader::new(data).expect("module reader"); 174 /// let section = reader.read().expect("type section"); 175 /// let section = reader.read().expect("function section"); 176 /// let section = reader.read().expect("table section"); 177 /// let section = reader.read().expect("element section"); 178 /// let mut element_reader = section.get_element_section_reader().expect("element section reader"); 179 /// for _ in 0..element_reader.get_count() { 180 /// let element = element_reader.read().expect("element"); 181 /// if let ElementKind::Active { init_expr, .. } = element.kind { 182 /// let mut init_expr_reader = init_expr.get_binary_reader(); 183 /// let op = init_expr_reader.read_operator().expect("op"); 184 /// println!("Init const: {:?}", op); 185 /// } 186 /// let mut items_reader = element.items.get_items_reader().expect("items reader"); 187 /// for _ in 0..items_reader.get_count() { 188 /// let item = items_reader.read().expect("item"); 189 /// println!(" Item: {:?}", item); 190 /// } 191 /// } 192 /// ``` read<'b>(&mut self) -> Result<Element<'b>> where 'a: 'b,193 pub fn read<'b>(&mut self) -> Result<Element<'b>> 194 where 195 'a: 'b, 196 { 197 let flags = self.reader.read_var_u32()?; 198 if (flags & !0b111) != 0 { 199 return Err(BinaryReaderError::new( 200 "invalid flags byte in element segment", 201 self.reader.original_position() - 1, 202 )); 203 } 204 let kind = if flags & 0b001 != 0 { 205 if flags & 0b010 != 0 { 206 ElementKind::Declared 207 } else { 208 ElementKind::Passive 209 } 210 } else { 211 let table_index = if flags & 0b010 == 0 { 212 0 213 } else { 214 self.reader.read_var_u32()? 215 }; 216 let init_expr = { 217 let expr_offset = self.reader.position; 218 self.reader.skip_init_expr()?; 219 let data = &self.reader.buffer[expr_offset..self.reader.position]; 220 InitExpr::new(data, self.reader.original_offset + expr_offset) 221 }; 222 ElementKind::Active { 223 table_index, 224 init_expr, 225 } 226 }; 227 let exprs = flags & 0b100 != 0; 228 let ty = if flags & 0b011 != 0 { 229 if exprs { 230 self.reader.read_type()? 231 } else { 232 match self.reader.read_external_kind()? { 233 ExternalKind::Function => Type::FuncRef, 234 _ => { 235 return Err(BinaryReaderError::new( 236 "only the function external type is supported in elem segment", 237 self.reader.original_position() - 1, 238 )); 239 } 240 } 241 } 242 } else { 243 Type::FuncRef 244 }; 245 let data_start = self.reader.position; 246 let items_count = self.reader.read_var_u32()?; 247 if exprs { 248 for _ in 0..items_count { 249 self.reader.skip_init_expr()?; 250 } 251 } else { 252 for _ in 0..items_count { 253 self.reader.skip_var_32()?; 254 } 255 } 256 let data_end = self.reader.position; 257 let items = ElementItems { 258 offset: self.reader.original_offset + data_start, 259 data: &self.reader.buffer[data_start..data_end], 260 exprs, 261 }; 262 Ok(Element { kind, items, ty }) 263 } 264 } 265 266 impl<'a> SectionReader for ElementSectionReader<'a> { 267 type Item = Element<'a>; read(&mut self) -> Result<Self::Item>268 fn read(&mut self) -> Result<Self::Item> { 269 ElementSectionReader::read(self) 270 } eof(&self) -> bool271 fn eof(&self) -> bool { 272 self.reader.eof() 273 } original_position(&self) -> usize274 fn original_position(&self) -> usize { 275 ElementSectionReader::original_position(self) 276 } 277 } 278 279 impl<'a> SectionWithLimitedItems for ElementSectionReader<'a> { get_count(&self) -> u32280 fn get_count(&self) -> u32 { 281 ElementSectionReader::get_count(self) 282 } 283 } 284 285 impl<'a> IntoIterator for ElementSectionReader<'a> { 286 type Item = Result<Element<'a>>; 287 type IntoIter = SectionIteratorLimited<ElementSectionReader<'a>>; 288 into_iter(self) -> Self::IntoIter289 fn into_iter(self) -> Self::IntoIter { 290 SectionIteratorLimited::new(self) 291 } 292 } 293