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 std::collections::HashSet;
17 use std::result;
18 use std::str;
19 
20 use crate::limits::{
21     MAX_WASM_FUNCTIONS, MAX_WASM_FUNCTION_LOCALS, MAX_WASM_GLOBALS, MAX_WASM_MEMORIES,
22     MAX_WASM_MEMORY_PAGES, MAX_WASM_TABLES, MAX_WASM_TYPES,
23 };
24 
25 use crate::binary_reader::BinaryReader;
26 
27 use crate::primitives::{
28     BinaryReaderError, ExternalKind, FuncType, GlobalType, ImportSectionEntryType, MemoryType,
29     Operator, ResizableLimits, Result, SectionCode, TableType, Type,
30 };
31 
32 use crate::operators_validator::{
33     is_subtype_supertype, FunctionEnd, OperatorValidator, OperatorValidatorConfig,
34     DEFAULT_OPERATOR_VALIDATOR_CONFIG,
35 };
36 use crate::parser::{Parser, ParserInput, ParserState, WasmDecoder};
37 use crate::{ElemSectionEntryTable, ElementItem};
38 use crate::{WasmFuncType, WasmGlobalType, WasmMemoryType, WasmModuleResources, WasmTableType};
39 
40 use crate::readers::FunctionBody;
41 
42 type ValidatorResult<'a, T> = result::Result<T, ParserState<'a>>;
43 
44 struct InitExpressionState {
45     ty: Type,
46     global_count: usize,
47     function_count: usize,
48     validated: bool,
49 }
50 
51 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
52 enum SectionOrderState {
53     Initial,
54     Type,
55     Import,
56     Function,
57     Table,
58     Memory,
59     Global,
60     Export,
61     Start,
62     Element,
63     DataCount,
64     Code,
65     Data,
66 }
67 
68 impl SectionOrderState {
from_section_code(code: &SectionCode) -> Option<SectionOrderState>69     pub fn from_section_code(code: &SectionCode) -> Option<SectionOrderState> {
70         match *code {
71             SectionCode::Type => Some(SectionOrderState::Type),
72             SectionCode::Import => Some(SectionOrderState::Import),
73             SectionCode::Function => Some(SectionOrderState::Function),
74             SectionCode::Table => Some(SectionOrderState::Table),
75             SectionCode::Memory => Some(SectionOrderState::Memory),
76             SectionCode::Global => Some(SectionOrderState::Global),
77             SectionCode::Export => Some(SectionOrderState::Export),
78             SectionCode::Start => Some(SectionOrderState::Start),
79             SectionCode::Element => Some(SectionOrderState::Element),
80             SectionCode::Code => Some(SectionOrderState::Code),
81             SectionCode::Data => Some(SectionOrderState::Data),
82             SectionCode::DataCount => Some(SectionOrderState::DataCount),
83             _ => None,
84         }
85     }
86 }
87 
88 #[derive(Copy, Clone)]
89 pub struct ValidatingParserConfig {
90     pub operator_config: OperatorValidatorConfig,
91 }
92 
93 const DEFAULT_VALIDATING_PARSER_CONFIG: ValidatingParserConfig = ValidatingParserConfig {
94     operator_config: DEFAULT_OPERATOR_VALIDATOR_CONFIG,
95 };
96 
97 struct ValidatingParserResources {
98     types: Vec<FuncType>,
99     tables: Vec<TableType>,
100     memories: Vec<MemoryType>,
101     globals: Vec<GlobalType>,
102     element_count: u32,
103     data_count: Option<u32>,
104     func_type_indices: Vec<u32>,
105 }
106 
107 impl<'a> WasmModuleResources for ValidatingParserResources {
108     type FuncType = crate::FuncType;
109     type TableType = crate::TableType;
110     type MemoryType = crate::MemoryType;
111     type GlobalType = crate::GlobalType;
112 
type_at(&self, at: u32) -> Option<&Self::FuncType>113     fn type_at(&self, at: u32) -> Option<&Self::FuncType> {
114         self.types.get(at as usize)
115     }
116 
table_at(&self, at: u32) -> Option<&Self::TableType>117     fn table_at(&self, at: u32) -> Option<&Self::TableType> {
118         self.tables.get(at as usize)
119     }
120 
memory_at(&self, at: u32) -> Option<&Self::MemoryType>121     fn memory_at(&self, at: u32) -> Option<&Self::MemoryType> {
122         self.memories.get(at as usize)
123     }
124 
global_at(&self, at: u32) -> Option<&Self::GlobalType>125     fn global_at(&self, at: u32) -> Option<&Self::GlobalType> {
126         self.globals.get(at as usize)
127     }
128 
func_type_id_at(&self, at: u32) -> Option<u32>129     fn func_type_id_at(&self, at: u32) -> Option<u32> {
130         self.func_type_indices.get(at as usize).copied()
131     }
132 
element_count(&self) -> u32133     fn element_count(&self) -> u32 {
134         self.element_count
135     }
136 
data_count(&self) -> u32137     fn data_count(&self) -> u32 {
138         self.data_count.unwrap_or(0)
139     }
140 }
141 
142 pub struct ValidatingParser<'a> {
143     parser: Parser<'a>,
144     validation_error: Option<ParserState<'a>>,
145     read_position: Option<usize>,
146     section_order_state: SectionOrderState,
147     resources: ValidatingParserResources,
148     current_func_index: u32,
149     func_imports_count: u32,
150     init_expression_state: Option<InitExpressionState>,
151     data_found: u32,
152     exported_names: HashSet<String>,
153     current_operator_validator: Option<OperatorValidator>,
154     config: ValidatingParserConfig,
155 }
156 
157 impl<'a> ValidatingParser<'a> {
new(bytes: &[u8], config: Option<ValidatingParserConfig>) -> ValidatingParser158     pub fn new(bytes: &[u8], config: Option<ValidatingParserConfig>) -> ValidatingParser {
159         ValidatingParser {
160             parser: Parser::new(bytes),
161             validation_error: None,
162             read_position: None,
163             section_order_state: SectionOrderState::Initial,
164             resources: ValidatingParserResources {
165                 types: Vec::new(),
166                 tables: Vec::new(),
167                 memories: Vec::new(),
168                 globals: Vec::new(),
169                 element_count: 0,
170                 data_count: None,
171                 func_type_indices: Vec::new(),
172             },
173             current_func_index: 0,
174             func_imports_count: 0,
175             current_operator_validator: None,
176             init_expression_state: None,
177             data_found: 0,
178             exported_names: HashSet::new(),
179             config: config.unwrap_or(DEFAULT_VALIDATING_PARSER_CONFIG),
180         }
181     }
182 
get_resources( &self, ) -> &dyn WasmModuleResources< FuncType = crate::FuncType, TableType = crate::TableType, MemoryType = crate::MemoryType, GlobalType = crate::GlobalType, >183     pub fn get_resources(
184         &self,
185     ) -> &dyn WasmModuleResources<
186         FuncType = crate::FuncType,
187         TableType = crate::TableType,
188         MemoryType = crate::MemoryType,
189         GlobalType = crate::GlobalType,
190     > {
191         &self.resources
192     }
193 
set_validation_error(&mut self, message: &'static str)194     fn set_validation_error(&mut self, message: &'static str) {
195         self.validation_error = Some(ParserState::Error(BinaryReaderError {
196             message,
197             offset: self.read_position.unwrap(),
198         }))
199     }
200 
create_error<T>(&self, message: &'static str) -> ValidatorResult<'a, T>201     fn create_error<T>(&self, message: &'static str) -> ValidatorResult<'a, T> {
202         Err(ParserState::Error(BinaryReaderError {
203             message,
204             offset: self.read_position.unwrap(),
205         }))
206     }
207 
check_value_type(&self, ty: Type) -> ValidatorResult<'a, ()>208     fn check_value_type(&self, ty: Type) -> ValidatorResult<'a, ()> {
209         match ty {
210             Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()),
211             Type::NullRef | Type::AnyFunc | Type::AnyRef => {
212                 if !self.config.operator_config.enable_reference_types {
213                     return self.create_error("reference types support is not enabled");
214                 }
215                 Ok(())
216             }
217             Type::V128 => {
218                 if !self.config.operator_config.enable_simd {
219                     return self.create_error("SIMD support is not enabled");
220                 }
221                 Ok(())
222             }
223             _ => self.create_error("invalid value type"),
224         }
225     }
226 
check_value_types(&self, types: &[Type]) -> ValidatorResult<'a, ()>227     fn check_value_types(&self, types: &[Type]) -> ValidatorResult<'a, ()> {
228         for ty in types {
229             self.check_value_type(*ty)?;
230         }
231         Ok(())
232     }
233 
check_limits(&self, limits: &ResizableLimits) -> ValidatorResult<'a, ()>234     fn check_limits(&self, limits: &ResizableLimits) -> ValidatorResult<'a, ()> {
235         if limits.maximum.is_some() && limits.initial > limits.maximum.unwrap() {
236             return self.create_error("maximum limits less than initial");
237         }
238         Ok(())
239     }
240 
check_func_type(&self, func_type: &FuncType) -> ValidatorResult<'a, ()>241     fn check_func_type(&self, func_type: &FuncType) -> ValidatorResult<'a, ()> {
242         if let Type::Func = func_type.form {
243             self.check_value_types(&*func_type.params)?;
244             self.check_value_types(&*func_type.returns)?;
245             if !self.config.operator_config.enable_multi_value && func_type.returns.len() > 1 {
246                 self.create_error("func type returns multiple values")
247             } else {
248                 Ok(())
249             }
250         } else {
251             self.create_error("type signature is not a func")
252         }
253     }
254 
check_table_type(&self, table_type: &TableType) -> ValidatorResult<'a, ()>255     fn check_table_type(&self, table_type: &TableType) -> ValidatorResult<'a, ()> {
256         match table_type.element_type {
257             Type::AnyFunc => {}
258             _ => {
259                 if !self.config.operator_config.enable_reference_types {
260                     return self.create_error("element is not anyfunc");
261                 }
262             }
263         }
264         self.check_limits(&table_type.limits)
265     }
266 
check_memory_type(&self, memory_type: &MemoryType) -> ValidatorResult<'a, ()>267     fn check_memory_type(&self, memory_type: &MemoryType) -> ValidatorResult<'a, ()> {
268         self.check_limits(&memory_type.limits)?;
269         let initial = memory_type.limits.initial;
270         if initial as usize > MAX_WASM_MEMORY_PAGES {
271             return self.create_error("memory initial value exceeds limit");
272         }
273         let maximum = memory_type.limits.maximum;
274         if maximum.is_some() && maximum.unwrap() as usize > MAX_WASM_MEMORY_PAGES {
275             return self.create_error("memory maximum value exceeds limit");
276         }
277         Ok(())
278     }
279 
check_global_type(&self, global_type: GlobalType) -> ValidatorResult<'a, ()>280     fn check_global_type(&self, global_type: GlobalType) -> ValidatorResult<'a, ()> {
281         self.check_value_type(global_type.content_type)
282     }
283 
check_import_entry(&self, import_type: &ImportSectionEntryType) -> ValidatorResult<'a, ()>284     fn check_import_entry(&self, import_type: &ImportSectionEntryType) -> ValidatorResult<'a, ()> {
285         match *import_type {
286             ImportSectionEntryType::Function(type_index) => {
287                 if self.resources.func_type_indices.len() >= MAX_WASM_FUNCTIONS {
288                     return self.create_error("functions count out of bounds");
289                 }
290                 if type_index as usize >= self.resources.types.len() {
291                     return self.create_error("type index out of bounds");
292                 }
293                 Ok(())
294             }
295             ImportSectionEntryType::Table(ref table_type) => {
296                 if !self.config.operator_config.enable_reference_types
297                     && self.resources.tables.len() >= MAX_WASM_TABLES
298                 {
299                     return self.create_error("tables count must be at most 1");
300                 }
301                 self.check_table_type(table_type)
302             }
303             ImportSectionEntryType::Memory(ref memory_type) => {
304                 if self.resources.memories.len() >= MAX_WASM_MEMORIES {
305                     return self.create_error("memory count must be at most 1");
306                 }
307                 self.check_memory_type(memory_type)
308             }
309             ImportSectionEntryType::Global(global_type) => {
310                 if self.resources.globals.len() >= MAX_WASM_GLOBALS {
311                     return self.create_error("functions count out of bounds");
312                 }
313                 self.check_global_type(global_type)
314             }
315         }
316     }
317 
check_init_expression_operator(&self, operator: &Operator) -> ValidatorResult<'a, ()>318     fn check_init_expression_operator(&self, operator: &Operator) -> ValidatorResult<'a, ()> {
319         let state = self.init_expression_state.as_ref().unwrap();
320         if state.validated {
321             return self.create_error("only one init_expr operator is expected");
322         }
323         let ty = match *operator {
324             Operator::I32Const { .. } => Type::I32,
325             Operator::I64Const { .. } => Type::I64,
326             Operator::F32Const { .. } => Type::F32,
327             Operator::F64Const { .. } => Type::F64,
328             Operator::RefNull => {
329                 if !self.config.operator_config.enable_reference_types {
330                     return self.create_error("reference types support is not enabled");
331                 }
332                 Type::NullRef
333             }
334             Operator::V128Const { .. } => {
335                 if !self.config.operator_config.enable_simd {
336                     return self.create_error("SIMD support is not enabled");
337                 }
338                 Type::V128
339             }
340             Operator::GlobalGet { global_index } => {
341                 if global_index as usize >= state.global_count {
342                     return self.create_error("init_expr global index out of bounds");
343                 }
344                 self.resources.globals[global_index as usize].content_type
345             }
346             Operator::RefFunc { function_index } => {
347                 if function_index as usize >= state.function_count {
348                     return self.create_error("init_expr function index out of bounds");
349                 }
350                 Type::AnyFunc
351             }
352             _ => return self.create_error("invalid init_expr operator"),
353         };
354         if !is_subtype_supertype(ty, state.ty) {
355             return self.create_error("invalid init_expr type");
356         }
357         Ok(())
358     }
359 
check_export_entry( &self, field: &str, kind: ExternalKind, index: u32, ) -> ValidatorResult<'a, ()>360     fn check_export_entry(
361         &self,
362         field: &str,
363         kind: ExternalKind,
364         index: u32,
365     ) -> ValidatorResult<'a, ()> {
366         if self.exported_names.contains(field) {
367             return self.create_error("non-unique export name");
368         }
369         match kind {
370             ExternalKind::Function => {
371                 if index as usize >= self.resources.func_type_indices.len() {
372                     return self.create_error("exported function index out of bounds");
373                 }
374             }
375             ExternalKind::Table => {
376                 if index as usize >= self.resources.tables.len() {
377                     return self.create_error("exported table index out of bounds");
378                 }
379             }
380             ExternalKind::Memory => {
381                 if index as usize >= self.resources.memories.len() {
382                     return self.create_error("exported memory index out of bounds");
383                 }
384             }
385             ExternalKind::Global => {
386                 if index as usize >= self.resources.globals.len() {
387                     return self.create_error("exported global index out of bounds");
388                 }
389             }
390         };
391         Ok(())
392     }
393 
check_start(&self, func_index: u32) -> ValidatorResult<'a, ()>394     fn check_start(&self, func_index: u32) -> ValidatorResult<'a, ()> {
395         if func_index as usize >= self.resources.func_type_indices.len() {
396             return self.create_error("start function index out of bounds");
397         }
398         let type_index = self.resources.func_type_indices[func_index as usize];
399         let ty = &self.resources.types[type_index as usize];
400         if !ty.params.is_empty() || !ty.returns.is_empty() {
401             return self.create_error("invlid start function type");
402         }
403         Ok(())
404     }
405 
process_begin_section(&self, code: &SectionCode) -> ValidatorResult<'a, SectionOrderState>406     fn process_begin_section(&self, code: &SectionCode) -> ValidatorResult<'a, SectionOrderState> {
407         let order_state = SectionOrderState::from_section_code(code);
408         Ok(match self.section_order_state {
409             SectionOrderState::Initial => match order_state {
410                 Some(section) => section,
411                 _ => SectionOrderState::Initial,
412             },
413             previous => {
414                 if let Some(order_state_unwraped) = order_state {
415                     if previous >= order_state_unwraped {
416                         return self.create_error("section out of order");
417                     }
418                     order_state_unwraped
419                 } else {
420                     previous
421                 }
422             }
423         })
424     }
425 
process_state(&mut self)426     fn process_state(&mut self) {
427         match *self.parser.last_state() {
428             ParserState::BeginWasm { version } => {
429                 if version != 1 {
430                     self.set_validation_error("bad wasm file version");
431                 }
432             }
433             ParserState::BeginSection { ref code, .. } => {
434                 let check = self.process_begin_section(code);
435                 if check.is_err() {
436                     self.validation_error = check.err();
437                 } else {
438                     self.section_order_state = check.ok().unwrap();
439                 }
440             }
441             ParserState::TypeSectionEntry(ref func_type) => {
442                 let check = self.check_func_type(func_type);
443                 if check.is_err() {
444                     self.validation_error = check.err();
445                 } else if self.resources.types.len() > MAX_WASM_TYPES {
446                     self.set_validation_error("types count is out of bounds");
447                 } else {
448                     self.resources.types.push(func_type.clone());
449                 }
450             }
451             ParserState::ImportSectionEntry { ref ty, .. } => {
452                 let check = self.check_import_entry(ty);
453                 if check.is_err() {
454                     self.validation_error = check.err();
455                 } else {
456                     match *ty {
457                         ImportSectionEntryType::Function(type_index) => {
458                             self.func_imports_count += 1;
459                             self.resources.func_type_indices.push(type_index);
460                         }
461                         ImportSectionEntryType::Table(ref table_type) => {
462                             self.resources.tables.push(table_type.clone());
463                         }
464                         ImportSectionEntryType::Memory(ref memory_type) => {
465                             self.resources.memories.push(memory_type.clone());
466                         }
467                         ImportSectionEntryType::Global(ref global_type) => {
468                             self.resources.globals.push(global_type.clone());
469                         }
470                     }
471                 }
472             }
473             ParserState::FunctionSectionEntry(type_index) => {
474                 if type_index as usize >= self.resources.types.len() {
475                     self.set_validation_error("func type index out of bounds");
476                 } else if self.resources.func_type_indices.len() >= MAX_WASM_FUNCTIONS {
477                     self.set_validation_error("functions count out of bounds");
478                 } else {
479                     self.resources.func_type_indices.push(type_index);
480                 }
481             }
482             ParserState::TableSectionEntry(ref table_type) => {
483                 if !self.config.operator_config.enable_reference_types
484                     && self.resources.tables.len() >= MAX_WASM_TABLES
485                 {
486                     self.set_validation_error("tables count must be at most 1");
487                 } else {
488                     self.validation_error = self.check_table_type(table_type).err();
489                     self.resources.tables.push(table_type.clone());
490                 }
491             }
492             ParserState::MemorySectionEntry(ref memory_type) => {
493                 if self.resources.memories.len() >= MAX_WASM_MEMORIES {
494                     self.set_validation_error("memories count must be at most 1");
495                 } else {
496                     self.validation_error = self.check_memory_type(memory_type).err();
497                     self.resources.memories.push(memory_type.clone());
498                 }
499             }
500             ParserState::BeginGlobalSectionEntry(global_type) => {
501                 if self.resources.globals.len() >= MAX_WASM_GLOBALS {
502                     self.set_validation_error("globals count out of bounds");
503                 } else {
504                     self.validation_error = self.check_global_type(global_type).err();
505                     self.init_expression_state = Some(InitExpressionState {
506                         ty: global_type.content_type,
507                         global_count: self.resources.globals.len(),
508                         function_count: self.resources.func_type_indices.len(),
509                         validated: false,
510                     });
511                     self.resources.globals.push(global_type);
512                 }
513             }
514             ParserState::BeginInitExpressionBody => {
515                 assert!(self.init_expression_state.is_some());
516             }
517             ParserState::InitExpressionOperator(ref operator) => {
518                 self.validation_error = self.check_init_expression_operator(operator).err();
519                 self.init_expression_state.as_mut().unwrap().validated = true;
520             }
521             ParserState::EndInitExpressionBody => {
522                 if !self.init_expression_state.as_ref().unwrap().validated {
523                     self.set_validation_error("init_expr is empty");
524                 }
525                 self.init_expression_state = None;
526             }
527             ParserState::ExportSectionEntry { field, kind, index } => {
528                 self.validation_error = self.check_export_entry(field, kind, index).err();
529                 self.exported_names.insert(String::from(field));
530             }
531             ParserState::StartSectionEntry(func_index) => {
532                 self.validation_error = self.check_start(func_index).err();
533             }
534             ParserState::DataCountSectionEntry(count) => {
535                 self.resources.data_count = Some(count);
536             }
537             ParserState::BeginElementSectionEntry { table, ty } => {
538                 self.resources.element_count += 1;
539                 if let ElemSectionEntryTable::Active(table_index) = table {
540                     let table = match self.resources.tables.get(table_index as usize) {
541                         Some(t) => t,
542                         None => {
543                             self.set_validation_error("element section table index out of bounds");
544                             return;
545                         }
546                     };
547                     if !is_subtype_supertype(ty, table.element_type) {
548                         self.set_validation_error("element_type != table type");
549                         return;
550                     }
551                     if !self.config.operator_config.enable_reference_types && ty != Type::AnyFunc {
552                         self.set_validation_error("element_type != anyfunc is not supported yet");
553                         return;
554                     }
555                     self.init_expression_state = Some(InitExpressionState {
556                         ty: Type::I32,
557                         global_count: self.resources.globals.len(),
558                         function_count: self.resources.func_type_indices.len(),
559                         validated: false,
560                     });
561                 }
562             }
563             ParserState::ElementSectionEntryBody(ref indices) => {
564                 for item in &**indices {
565                     if let ElementItem::Func(func_index) = item {
566                         if *func_index as usize >= self.resources.func_type_indices.len() {
567                             self.set_validation_error("element func index out of bounds");
568                             break;
569                         }
570                     }
571                 }
572             }
573             ParserState::BeginFunctionBody { .. } => {
574                 let index = (self.current_func_index + self.func_imports_count) as usize;
575                 if index as usize >= self.resources.func_type_indices.len() {
576                     self.set_validation_error("func type is not defined");
577                 }
578             }
579             ParserState::FunctionBodyLocals { ref locals } => {
580                 let index = (self.current_func_index + self.func_imports_count) as usize;
581                 let func_type =
582                     &self.resources.types[self.resources.func_type_indices[index] as usize];
583                 let operator_config = self.config.operator_config;
584                 self.current_operator_validator =
585                     Some(OperatorValidator::new(func_type, locals, operator_config));
586             }
587             ParserState::CodeOperator(ref operator) => {
588                 let check = self
589                     .current_operator_validator
590                     .as_mut()
591                     .unwrap()
592                     .process_operator(operator, &self.resources);
593 
594                 if let Err(err) = check {
595                     self.set_validation_error(err);
596                 }
597             }
598             ParserState::EndFunctionBody => {
599                 let check = self
600                     .current_operator_validator
601                     .as_ref()
602                     .unwrap()
603                     .process_end_function();
604                 if let Err(err) = check {
605                     self.set_validation_error(err);
606                 }
607                 self.current_func_index += 1;
608                 self.current_operator_validator = None;
609             }
610             ParserState::BeginDataSectionEntryBody(_) => {
611                 self.data_found += 1;
612             }
613             ParserState::BeginActiveDataSectionEntry(memory_index) => {
614                 if memory_index as usize >= self.resources.memories.len() {
615                     self.set_validation_error("data section memory index out of bounds");
616                 } else {
617                     self.init_expression_state = Some(InitExpressionState {
618                         ty: Type::I32,
619                         global_count: self.resources.globals.len(),
620                         function_count: self.resources.func_type_indices.len(),
621                         validated: false,
622                     });
623                 }
624             }
625             ParserState::EndWasm => {
626                 if self.resources.func_type_indices.len()
627                     != self.current_func_index as usize + self.func_imports_count as usize
628                 {
629                     self.set_validation_error(
630                         "function and code section have inconsistent lengths",
631                     );
632                 }
633                 if let Some(data_count) = self.resources.data_count {
634                     if data_count != self.data_found {
635                         self.set_validation_error("data count section and passive data mismatch");
636                     }
637                 }
638             }
639             _ => (),
640         };
641     }
642 
create_validating_operator_parser<'b>(&mut self) -> ValidatingOperatorParser<'b> where 'a: 'b,643     pub fn create_validating_operator_parser<'b>(&mut self) -> ValidatingOperatorParser<'b>
644     where
645         'a: 'b,
646     {
647         let func_body_offset = match *self.last_state() {
648             ParserState::BeginFunctionBody { .. } => self.parser.current_position(),
649             _ => panic!("Invalid reader state"),
650         };
651         self.read();
652         let operator_validator = match *self.last_state() {
653             ParserState::FunctionBodyLocals { ref locals } => {
654                 let index = (self.current_func_index + self.func_imports_count) as usize;
655                 let func_type =
656                     &self.resources.types[self.resources.func_type_indices[index] as usize];
657                 let operator_config = self.config.operator_config;
658                 OperatorValidator::new(func_type, locals, operator_config)
659             }
660             _ => panic!("Invalid reader state"),
661         };
662         let reader = self.create_binary_reader();
663         ValidatingOperatorParser::new(operator_validator, reader, func_body_offset)
664     }
665 }
666 
667 impl<'a> WasmDecoder<'a> for ValidatingParser<'a> {
read(&mut self) -> &ParserState<'a>668     fn read(&mut self) -> &ParserState<'a> {
669         if self.validation_error.is_some() {
670             panic!("Parser in error state: validation");
671         }
672         self.read_position = Some(self.parser.current_position());
673         self.parser.read();
674         self.process_state();
675         self.last_state()
676     }
677 
push_input(&mut self, input: ParserInput)678     fn push_input(&mut self, input: ParserInput) {
679         match input {
680             ParserInput::SkipSection => panic!("Not supported"),
681             ParserInput::ReadSectionRawData => panic!("Not supported"),
682             ParserInput::SkipFunctionBody => {
683                 self.current_func_index += 1;
684                 self.parser.push_input(input);
685             }
686             _ => self.parser.push_input(input),
687         }
688     }
689 
read_with_input(&mut self, input: ParserInput) -> &ParserState<'a>690     fn read_with_input(&mut self, input: ParserInput) -> &ParserState<'a> {
691         self.push_input(input);
692         self.read()
693     }
694 
create_binary_reader<'b>(&mut self) -> BinaryReader<'b> where 'a: 'b,695     fn create_binary_reader<'b>(&mut self) -> BinaryReader<'b>
696     where
697         'a: 'b,
698     {
699         if let ParserState::BeginSection { .. } = *self.parser.last_state() {
700             panic!("Not supported");
701         }
702         self.parser.create_binary_reader()
703     }
704 
last_state(&self) -> &ParserState<'a>705     fn last_state(&self) -> &ParserState<'a> {
706         if self.validation_error.is_some() {
707             self.validation_error.as_ref().unwrap()
708         } else {
709             self.parser.last_state()
710         }
711     }
712 }
713 
714 pub struct ValidatingOperatorParser<'b> {
715     operator_validator: OperatorValidator,
716     reader: BinaryReader<'b>,
717     func_body_offset: usize,
718     end_function: bool,
719 }
720 
721 impl<'b> ValidatingOperatorParser<'b> {
new<'c>( operator_validator: OperatorValidator, reader: BinaryReader<'c>, func_body_offset: usize, ) -> ValidatingOperatorParser<'c> where 'b: 'c,722     pub(crate) fn new<'c>(
723         operator_validator: OperatorValidator,
724         reader: BinaryReader<'c>,
725         func_body_offset: usize,
726     ) -> ValidatingOperatorParser<'c>
727     where
728         'b: 'c,
729     {
730         ValidatingOperatorParser {
731             operator_validator,
732             reader,
733             func_body_offset,
734             end_function: false,
735         }
736     }
737 
eof(&self) -> bool738     pub fn eof(&self) -> bool {
739         self.end_function
740     }
741 
current_position(&self) -> usize742     pub fn current_position(&self) -> usize {
743         self.reader.current_position()
744     }
745 
is_dead_code(&self) -> bool746     pub fn is_dead_code(&self) -> bool {
747         self.operator_validator.is_dead_code()
748     }
749 
750     /// Creates a BinaryReader when current state is ParserState::BeginSection
751     /// or ParserState::BeginFunctionBody.
752     ///
753     /// # Examples
754     /// ```
755     /// # let data = &[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0, 0x1, 0x84,
756     /// #              0x80, 0x80, 0x80, 0x0, 0x1, 0x60, 0x0, 0x0, 0x3, 0x83,
757     /// #              0x80, 0x80, 0x80, 0x0, 0x2, 0x0, 0x0, 0x6, 0x81, 0x80,
758     /// #              0x80, 0x80, 0x0, 0x0, 0xa, 0x91, 0x80, 0x80, 0x80, 0x0,
759     /// #              0x2, 0x83, 0x80, 0x80, 0x80, 0x0, 0x0, 0x1, 0xb, 0x83,
760     /// #              0x80, 0x80, 0x80, 0x0, 0x0, 0x0, 0xb];
761     /// use wasmparser::{WasmDecoder, ParserState, ValidatingParser};
762     /// let mut parser = ValidatingParser::new(data, None);
763     /// let mut i = 0;
764     /// loop {
765     ///     {
766     ///         match *parser.read() {
767     ///             ParserState::Error(_) |
768     ///             ParserState::EndWasm => break,
769     ///             ParserState::BeginFunctionBody {..} => (),
770     ///             _ => continue
771     ///         }
772     ///     }
773     ///     let mut reader = parser.create_validating_operator_parser();
774     ///     println!("Function {}", i);
775     ///     i += 1;
776     ///     while !reader.eof() {
777     ///       let read = reader.next(parser.get_resources());
778     ///       if let Ok(ref op) = read {
779     ///           println!("  {:?}", op);
780     ///       } else {
781     ///           panic!("  Bad wasm code {:?}", read.err());
782     ///       }
783     ///     }
784     /// }
785     /// ```
next<'c, F: WasmFuncType, T: WasmTableType, M: WasmMemoryType, G: WasmGlobalType>( &mut self, resources: &dyn WasmModuleResources< FuncType = F, TableType = T, MemoryType = M, GlobalType = G, >, ) -> Result<Operator<'c>> where 'b: 'c,786     pub fn next<'c, F: WasmFuncType, T: WasmTableType, M: WasmMemoryType, G: WasmGlobalType>(
787         &mut self,
788         resources: &dyn WasmModuleResources<
789             FuncType = F,
790             TableType = T,
791             MemoryType = M,
792             GlobalType = G,
793         >,
794     ) -> Result<Operator<'c>>
795     where
796         'b: 'c,
797     {
798         let op = self.reader.read_operator()?;
799         match self.operator_validator.process_operator(&op, resources) {
800             Err(err) => {
801                 return Err(BinaryReaderError {
802                     message: err,
803                     offset: self.func_body_offset + self.reader.current_position(),
804                 });
805             }
806             Ok(FunctionEnd::Yes) => {
807                 self.end_function = true;
808                 if !self.reader.eof() {
809                     return Err(BinaryReaderError {
810                         message: "unexpected end of function",
811                         offset: self.func_body_offset + self.reader.current_position(),
812                     });
813                 }
814             }
815             _ => (),
816         };
817         Ok(op)
818     }
819 }
820 
821 /// Test whether the given buffer contains a valid WebAssembly function.
822 /// The resources parameter contains all needed data to validate the operators.
validate_function_body< F: WasmFuncType, T: WasmTableType, M: WasmMemoryType, G: WasmGlobalType, >( bytes: &[u8], offset: usize, func_index: u32, resources: &dyn WasmModuleResources< FuncType = F, TableType = T, MemoryType = M, GlobalType = G, >, operator_config: Option<OperatorValidatorConfig>, ) -> Result<()>823 pub fn validate_function_body<
824     F: WasmFuncType,
825     T: WasmTableType,
826     M: WasmMemoryType,
827     G: WasmGlobalType,
828 >(
829     bytes: &[u8],
830     offset: usize,
831     func_index: u32,
832     resources: &dyn WasmModuleResources<
833         FuncType = F,
834         TableType = T,
835         MemoryType = M,
836         GlobalType = G,
837     >,
838     operator_config: Option<OperatorValidatorConfig>,
839 ) -> Result<()> {
840     let operator_config = operator_config.unwrap_or(DEFAULT_OPERATOR_VALIDATOR_CONFIG);
841     let function_body = FunctionBody::new(offset, bytes);
842     let mut locals_reader = function_body.get_locals_reader()?;
843     let local_count = locals_reader.get_count() as usize;
844     if local_count > MAX_WASM_FUNCTION_LOCALS {
845         return Err(BinaryReaderError {
846             message: "locals exceed maximum",
847             offset: locals_reader.original_position(),
848         });
849     }
850     let mut locals: Vec<(u32, Type)> = Vec::with_capacity(local_count);
851     let mut locals_total: usize = 0;
852     for _ in 0..local_count {
853         let (count, ty) = locals_reader.read()?;
854         locals_total =
855             locals_total
856                 .checked_add(count as usize)
857                 .ok_or_else(|| BinaryReaderError {
858                     message: "locals overflow",
859                     offset: locals_reader.original_position(),
860                 })?;
861         if locals_total > MAX_WASM_FUNCTION_LOCALS {
862             return Err(BinaryReaderError {
863                 message: "locals exceed maximum",
864                 offset: locals_reader.original_position(),
865             });
866         }
867         locals.push((count, ty));
868     }
869     let operators_reader = function_body.get_operators_reader()?;
870     let func_type_index = resources
871         .func_type_id_at(func_index)
872         // Note: This was an out-of-bounds access before the change to return `Option`
873         // so I assumed it is considered a bug to access a non-existing function
874         // id here and went with panicking instead of returning a proper error.
875         .expect("the function index of the validated function itself is out of bounds");
876     let func_type = resources
877         .type_at(func_type_index)
878         // Note: This was an out-of-bounds access before the change to return `Option`
879         // so I assumed it is considered a bug to access a non-existing function
880         // id here and went with panicking instead of returning a proper error.
881         .expect("the function type indexof the validated function itself is out of bounds");
882     let mut operator_validator = OperatorValidator::new(func_type, &locals, operator_config);
883     let mut eof_found = false;
884     let mut last_op = 0;
885     for item in operators_reader.into_iter_with_offsets() {
886         let (ref op, offset) = item?;
887         match operator_validator
888             .process_operator(op, resources)
889             .map_err(|message| BinaryReaderError { message, offset })?
890         {
891             FunctionEnd::Yes => {
892                 eof_found = true;
893             }
894             FunctionEnd::No => {
895                 last_op = offset;
896             }
897         }
898     }
899     if !eof_found {
900         return Err(BinaryReaderError {
901             message: "end of function not found",
902             offset: last_op,
903         });
904     }
905     Ok(())
906 }
907 
908 /// Test whether the given buffer contains a valid WebAssembly module,
909 /// analogous to WebAssembly.validate in the JS API.
validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> Result<()>910 pub fn validate(bytes: &[u8], config: Option<ValidatingParserConfig>) -> Result<()> {
911     let mut parser = ValidatingParser::new(bytes, config);
912     let mut parser_input = None;
913     let mut func_ranges = Vec::new();
914     loop {
915         let next_input = parser_input.take().unwrap_or(ParserInput::Default);
916         let state = parser.read_with_input(next_input);
917         match *state {
918             ParserState::EndWasm => break,
919             ParserState::Error(e) => return Err(e),
920             ParserState::BeginFunctionBody { range } => {
921                 parser_input = Some(ParserInput::SkipFunctionBody);
922                 func_ranges.push(range);
923             }
924             _ => (),
925         }
926     }
927     let operator_config = config.map(|c| c.operator_config);
928     for (i, range) in func_ranges.into_iter().enumerate() {
929         let function_body = range.slice(bytes);
930         let function_index = i as u32 + parser.func_imports_count;
931         validate_function_body(
932             function_body,
933             range.start,
934             function_index,
935             &parser.resources,
936             operator_config,
937         )?;
938     }
939     Ok(())
940 }
941 
942 #[test]
test_validate()943 fn test_validate() {
944     assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0], None).is_ok());
945     assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x2, 0x0, 0x0, 0x0], None).is_err());
946 }
947