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 crate::limits::*;
17 use crate::ResizableLimits64;
18 use crate::WasmModuleResources;
19 use crate::{Alias, ExternalKind, Import, ImportSectionEntryType};
20 use crate::{BinaryReaderError, EventType, GlobalType, MemoryType, Range, Result, TableType, Type};
21 use crate::{DataKind, ElementItem, ElementKind, InitExpr, Instance, Operator};
22 use crate::{FuncType, ResizableLimits, SectionReader, SectionWithLimitedItems};
23 use crate::{FunctionBody, Parser, Payload};
24 use std::collections::{HashMap, HashSet};
25 use std::mem;
26 use std::sync::Arc;
27
28 /// Test whether the given buffer contains a valid WebAssembly module,
29 /// analogous to [`WebAssembly.validate`][js] in the JS API.
30 ///
31 /// This functions requires the wasm module is entirely resident in memory and
32 /// is specified by `bytes`. Additionally this validates the given bytes with
33 /// the default set of WebAssembly features implemented by `wasmparser`.
34 ///
35 /// For more fine-tuned control over validation it's recommended to review the
36 /// documentation of [`Validator`].
37 ///
38 /// [js]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate
validate(bytes: &[u8]) -> Result<()>39 pub fn validate(bytes: &[u8]) -> Result<()> {
40 Validator::new().validate_all(bytes)
41 }
42
43 #[test]
test_validate()44 fn test_validate() {
45 assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0]).is_ok());
46 assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x2, 0x0, 0x0, 0x0]).is_err());
47 }
48
49 mod func;
50 pub use func::FuncValidator;
51
52 /// Validator for a WebAssembly binary module.
53 ///
54 /// This structure encapsulates state necessary to validate a WebAssembly
55 /// binary. This implements validation as defined by the [core
56 /// specification][core]. A `Validator` is designed, like
57 /// [`Parser`], to accept incremental input over time.
58 /// Additionally a `Validator` is also designed for parallel validation of
59 /// functions as they are received.
60 ///
61 /// It's expected that you'll be using a [`Parser`] in tandem with a
62 /// `Validator`. As each [`Payload`](crate::Payload) is received from a
63 /// [`Parser`] you'll pass it into a `Validator` to test the validity of the
64 /// payload. Note that all payloads received from a [`Parser`] are expected to
65 /// be passed to a [`Validator`]. For example if you receive
66 /// [`Payload::TypeSection`](crate::Payload) you'll call
67 /// [`Validator::type_section`] to validate this.
68 ///
69 /// The design of [`Validator`] is intended that you'll interleave, in your own
70 /// application's processing, calls to validation. Each variant, after it's
71 /// received, will be validated and then your application would proceed as
72 /// usual. At all times, however, you'll have access to the [`Validator`] and
73 /// the validation context up to that point. This enables applications to check
74 /// the types of functions and learn how many globals there are, for example.
75 ///
76 /// [core]: https://webassembly.github.io/spec/core/valid/index.html
77 #[derive(Default)]
78 pub struct Validator {
79 /// The current module that we're validating.
80 cur: Module,
81
82 /// With module linking this is the list of parent modules to this module,
83 /// sorted from oldest to most recent.
84 parents: Vec<Module>,
85
86 /// This is the global list of all types shared by this validator which all
87 /// modules will reference.
88 types: SnapshotList<TypeDef>,
89
90 /// Enabled WebAssembly feature flags, dictating what's valid and what
91 /// isn't.
92 features: WasmFeatures,
93
94 /// The current byte-level offset in the wasm binary. This is updated to
95 /// produce error messages in `create_error`.
96 offset: usize,
97 }
98
99 #[derive(Default)]
100 struct Module {
101 /// Internal state that is incrementally built-up for the module being
102 /// validate. This houses type information for all wasm items, like
103 /// functions. Note that this starts out as a solely owned `Arc<T>` so we can
104 /// get mutable access, but after we get to the code section this is never
105 /// mutated to we can clone it cheaply and hand it to sub-validators.
106 state: arc::MaybeOwned<ModuleState>,
107
108 /// Where we are, order-wise, in the wasm binary.
109 order: Order,
110
111 /// The number of data segments we ended up finding in this module, or 0 if
112 /// they either weren't present or none were found.
113 data_found: u32,
114
115 /// The number of functions we expect to be defined in the code section, or
116 /// basically the length of the function section if it was found. The next
117 /// index is where we are, in the code section index space, for the next
118 /// entry in the code section (used to figure out what type is next for the
119 /// function being validated).
120 expected_code_bodies: Option<u32>,
121 code_section_index: usize,
122 }
123
124 #[derive(Default)]
125 struct ModuleState {
126 /// This is a snapshot of `validator.types` when it is created. This is not
127 /// initially filled in but once everything in a module except the code
128 /// section has been parsed then this will be filled in.
129 ///
130 /// Note that this `ModuleState` will be a separately-owned structure living
131 /// in each function's validator. This is done to allow parallel validation
132 /// of functions while the main module is possibly still being parsed.
133 all_types: Option<Arc<SnapshotList<TypeDef>>>,
134
135 types: Vec<usize>, // pointer into `validator.types`
136 tables: Vec<TableType>,
137 memories: Vec<MemoryType>,
138 globals: Vec<GlobalType>,
139 element_types: Vec<Type>,
140 data_count: Option<u32>,
141 code_type_indexes: Vec<u32>, // pointer into `types` above
142 func_types: Vec<usize>, // pointer into `validator.types`
143 events: Vec<usize>, // pointer into `validator.types`
144 submodules: Vec<usize>, // pointer into `validator.types`
145 instances: Vec<usize>, // pointer into `validator.types`
146 function_references: HashSet<u32>,
147
148 // This is populated when we hit the export section
149 exports: NameSet,
150
151 // This is populated as we visit import sections, which might be
152 // incrementally in the face of a module-linking-using module.
153 imports: NameSet,
154 }
155
156 /// Flags for features that are enabled for validation.
157 #[derive(Hash, Debug, Copy, Clone)]
158 pub struct WasmFeatures {
159 /// The WebAssembly reference types proposal (enabled by default)
160 pub reference_types: bool,
161 /// The WebAssembly multi-value proposal (enabled by default)
162 pub multi_value: bool,
163 /// The WebAssembly bulk memory operations proposal (enabled by default)
164 pub bulk_memory: bool,
165 /// The WebAssembly module linking proposal
166 pub module_linking: bool,
167 /// The WebAssembly SIMD proposal
168 pub simd: bool,
169 /// The WebAssembly threads proposal
170 pub threads: bool,
171 /// The WebAssembly tail-call proposal
172 pub tail_call: bool,
173 /// Whether or not only deterministic instructions are allowed
174 pub deterministic_only: bool,
175 /// The WebAssembly multi memory proposal
176 pub multi_memory: bool,
177 /// The WebAssembly exception handling proposal
178 pub exceptions: bool,
179 /// The WebAssembly memory64 proposal
180 pub memory64: bool,
181 }
182
183 impl Default for WasmFeatures {
default() -> WasmFeatures184 fn default() -> WasmFeatures {
185 WasmFeatures {
186 // off-by-default features
187 module_linking: false,
188 simd: false,
189 threads: false,
190 tail_call: false,
191 multi_memory: false,
192 exceptions: false,
193 memory64: false,
194 deterministic_only: cfg!(feature = "deterministic"),
195
196 // on-by-default features
197 bulk_memory: true,
198 multi_value: true,
199 reference_types: true,
200 }
201 }
202 }
203
204 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug)]
205 enum Order {
206 Initial,
207 AfterHeader,
208 Type,
209 Import,
210 ModuleLinkingHeader,
211 Function,
212 Table,
213 Memory,
214 Event,
215 Global,
216 Export,
217 Start,
218 Element,
219 DataCount,
220 Code,
221 Data,
222 }
223
224 impl Default for Order {
default() -> Order225 fn default() -> Order {
226 Order::Initial
227 }
228 }
229
230 enum TypeDef {
231 Func(FuncType),
232 Module(ModuleType),
233 Instance(InstanceType),
234 }
235
236 impl TypeDef {
unwrap_func(&self) -> &FuncType237 fn unwrap_func(&self) -> &FuncType {
238 match self {
239 TypeDef::Func(f) => f,
240 _ => panic!("not a function type"),
241 }
242 }
243
unwrap_module(&self) -> &ModuleType244 fn unwrap_module(&self) -> &ModuleType {
245 match self {
246 TypeDef::Module(f) => f,
247 _ => panic!("not a module type"),
248 }
249 }
250
unwrap_instance(&self) -> &InstanceType251 fn unwrap_instance(&self) -> &InstanceType {
252 match self {
253 TypeDef::Instance(f) => f,
254 _ => panic!("not an instance type"),
255 }
256 }
257 }
258
259 struct ModuleType {
260 type_size: u32,
261 imports: HashMap<String, EntityType>,
262 exports: HashMap<String, EntityType>,
263 }
264
265 #[derive(Default)]
266 struct InstanceType {
267 type_size: u32,
268 exports: HashMap<String, EntityType>,
269 }
270
271 #[derive(Clone)]
272 enum EntityType {
273 Global(GlobalType),
274 Memory(MemoryType),
275 Table(TableType),
276 Func(usize), // pointer into `validator.types`
277 Module(usize), // pointer into `validator.types`
278 Instance(usize), // pointer into `validator.types`
279 Event(usize), // pointer into `validator.types`
280 }
281
282 /// Possible return values from [`Validator::payload`].
283 pub enum ValidPayload<'a> {
284 /// The payload validated, no further action need be taken.
285 Ok,
286 /// The payload validated, but it started a nested module.
287 ///
288 /// This result indicates that the specified parser should be used instead
289 /// of the currently-used parser until this returned one ends.
290 Submodule(Parser),
291 /// A function was found to be validate.
292 Func(FuncValidator<ValidatorResources>, FunctionBody<'a>),
293 }
294
295 impl Validator {
296 /// Creates a new [`Validator`] ready to validate a WebAssembly module.
297 ///
298 /// The new validator will receive payloads parsed from
299 /// [`Parser`], and expects the first payload received to be
300 /// the version header from the parser.
new() -> Validator301 pub fn new() -> Validator {
302 Validator::default()
303 }
304
305 /// Configures the enabled WebAssembly features for this `Validator`.
wasm_features(&mut self, features: WasmFeatures) -> &mut Validator306 pub fn wasm_features(&mut self, features: WasmFeatures) -> &mut Validator {
307 self.features = features;
308 self
309 }
310
311 /// Validates an entire in-memory module with this validator.
312 ///
313 /// This function will internally create a [`Parser`] to parse the `bytes`
314 /// provided. The entire wasm module specified by `bytes` will be parsed and
315 /// validated. Parse and validation errors will be returned through
316 /// `Err(_)`, and otherwise a successful validation means `Ok(())` is
317 /// returned.
validate_all(&mut self, bytes: &[u8]) -> Result<()>318 pub fn validate_all(&mut self, bytes: &[u8]) -> Result<()> {
319 let mut functions_to_validate = Vec::new();
320 for payload in Parser::new(0).parse_all(bytes) {
321 if let ValidPayload::Func(a, b) = self.payload(&payload?)? {
322 functions_to_validate.push((a, b));
323 }
324 }
325
326 for (mut validator, body) in functions_to_validate {
327 validator.validate(&body)?;
328 }
329 Ok(())
330 }
331
332 /// Convenience function to validate a single [`Payload`].
333 ///
334 /// This function is intended to be used as a convenience. It will
335 /// internally perform any validation necessary to validate the [`Payload`]
336 /// provided. The convenience part is that you're likely already going to
337 /// be matching on [`Payload`] in your application, at which point it's more
338 /// appropriate to call the individual methods on [`Validator`] per-variant
339 /// in [`Payload`], such as [`Validator::type_section`].
340 ///
341 /// This function returns a [`ValidPayload`] variant on success, indicating
342 /// one of a few possible actions that need to be taken after a payload is
343 /// validated. For example function contents are not validated here, they're
344 /// returned through [`ValidPayload`] for validation by the caller.
payload<'a>(&mut self, payload: &Payload<'a>) -> Result<ValidPayload<'a>>345 pub fn payload<'a>(&mut self, payload: &Payload<'a>) -> Result<ValidPayload<'a>> {
346 use crate::Payload::*;
347 match payload {
348 Version { num, range } => self.version(*num, range)?,
349 TypeSection(s) => self.type_section(s)?,
350 ImportSection(s) => self.import_section(s)?,
351 AliasSection(s) => self.alias_section(s)?,
352 InstanceSection(s) => self.instance_section(s)?,
353 FunctionSection(s) => self.function_section(s)?,
354 TableSection(s) => self.table_section(s)?,
355 MemorySection(s) => self.memory_section(s)?,
356 EventSection(s) => self.event_section(s)?,
357 GlobalSection(s) => self.global_section(s)?,
358 ExportSection(s) => self.export_section(s)?,
359 StartSection { func, range } => self.start_section(*func, range)?,
360 ElementSection(s) => self.element_section(s)?,
361 DataCountSection { count, range } => self.data_count_section(*count, range)?,
362 CodeSectionStart {
363 count,
364 range,
365 size: _,
366 } => self.code_section_start(*count, range)?,
367 CodeSectionEntry(body) => {
368 let func_validator = self.code_section_entry()?;
369 return Ok(ValidPayload::Func(func_validator, body.clone()));
370 }
371 ModuleSectionStart {
372 count,
373 range,
374 size: _,
375 } => self.module_section_start(*count, range)?,
376 DataSection(s) => self.data_section(s)?,
377 End => self.end()?,
378
379 CustomSection { .. } => {} // no validation for custom sections
380 UnknownSection { id, range, .. } => self.unknown_section(*id, range)?,
381 ModuleSectionEntry { parser, .. } => {
382 self.module_section_entry();
383 return Ok(ValidPayload::Submodule(parser.clone()));
384 }
385 }
386 Ok(ValidPayload::Ok)
387 }
388
create_error<T>(&self, msg: impl Into<String>) -> Result<T>389 fn create_error<T>(&self, msg: impl Into<String>) -> Result<T> {
390 Err(BinaryReaderError::new(msg.into(), self.offset))
391 }
392
393 /// Validates [`Payload::Version`](crate::Payload)
version(&mut self, num: u32, range: &Range) -> Result<()>394 pub fn version(&mut self, num: u32, range: &Range) -> Result<()> {
395 self.offset = range.start;
396 if self.cur.order != Order::Initial {
397 return self.create_error("wasm version header out of order");
398 }
399 self.cur.order = Order::AfterHeader;
400 if num != 1 {
401 return self.create_error("bad wasm file version");
402 }
403 Ok(())
404 }
405
update_order(&mut self, order: Order) -> Result<()>406 fn update_order(&mut self, order: Order) -> Result<()> {
407 let prev = mem::replace(&mut self.cur.order, order);
408 // If the previous section came before this section, then that's always
409 // valid.
410 if prev < order {
411 return Ok(());
412 }
413 // ... otherwise if this is a repeated section then only the "module
414 // linking header" is allows to have repeats
415 if prev == self.cur.order && self.cur.order == Order::ModuleLinkingHeader {
416 return Ok(());
417 }
418 self.create_error("section out of order")
419 }
420
header_order(&mut self, order: Order) -> Order421 fn header_order(&mut self, order: Order) -> Order {
422 if self.features.module_linking {
423 Order::ModuleLinkingHeader
424 } else {
425 order
426 }
427 }
428
get_type(&self, idx: u32) -> Result<&TypeDef>429 fn get_type(&self, idx: u32) -> Result<&TypeDef> {
430 match self.cur.state.types.get(idx as usize) {
431 Some(t) => Ok(&self.types[*t]),
432 None => self.create_error(format!("unknown type {}: type index out of bounds", idx)),
433 }
434 }
435
get_table(&self, idx: u32) -> Result<&TableType>436 fn get_table(&self, idx: u32) -> Result<&TableType> {
437 match self.cur.state.tables.get(idx as usize) {
438 Some(t) => Ok(t),
439 None => self.create_error(format!("unknown table {}: table index out of bounds", idx)),
440 }
441 }
442
get_memory(&self, idx: u32) -> Result<&MemoryType>443 fn get_memory(&self, idx: u32) -> Result<&MemoryType> {
444 match self.cur.state.memories.get(idx as usize) {
445 Some(t) => Ok(t),
446 None => self.create_error(format!(
447 "unknown memory {}: memory index out of bounds",
448 idx,
449 )),
450 }
451 }
452
get_global(&self, idx: u32) -> Result<&GlobalType>453 fn get_global(&self, idx: u32) -> Result<&GlobalType> {
454 match self.cur.state.globals.get(idx as usize) {
455 Some(t) => Ok(t),
456 None => self.create_error(format!(
457 "unknown global {}: global index out of bounds",
458 idx,
459 )),
460 }
461 }
462
get_func_type(&self, func_idx: u32) -> Result<&FuncType>463 fn get_func_type(&self, func_idx: u32) -> Result<&FuncType> {
464 match self.cur.state.func_types.get(func_idx as usize) {
465 Some(t) => Ok(self.types[*t].unwrap_func()),
466 None => self.create_error(format!(
467 "unknown function {}: func index out of bounds",
468 func_idx,
469 )),
470 }
471 }
472
get_module_type(&self, module_idx: u32) -> Result<&ModuleType>473 fn get_module_type(&self, module_idx: u32) -> Result<&ModuleType> {
474 match self.cur.state.submodules.get(module_idx as usize) {
475 Some(t) => Ok(self.types[*t].unwrap_module()),
476 None => self.create_error("unknown module: module index out of bounds"),
477 }
478 }
479
get_instance_type(&self, instance_idx: u32) -> Result<&InstanceType>480 fn get_instance_type(&self, instance_idx: u32) -> Result<&InstanceType> {
481 match self.cur.state.instances.get(instance_idx as usize) {
482 Some(t) => Ok(self.types[*t].unwrap_instance()),
483 None => self.create_error("unknown instance: instance index out of bounds"),
484 }
485 }
486
func_type_at(&self, type_index: u32) -> Result<&FuncType>487 fn func_type_at(&self, type_index: u32) -> Result<&FuncType> {
488 let def = self.get_type(type_index)?;
489 match def {
490 TypeDef::Func(item) => Ok(item),
491 _ => self.create_error("type index is not a function"),
492 }
493 }
494
module_type_at(&self, type_index: u32) -> Result<&ModuleType>495 fn module_type_at(&self, type_index: u32) -> Result<&ModuleType> {
496 if !self.features.module_linking {
497 return self.create_error("module linking proposal not enabled");
498 }
499 let ty = self.get_type(type_index)?;
500 match ty {
501 TypeDef::Module(item) => Ok(item),
502 _ => self.create_error("type index is not a module"),
503 }
504 }
505
instance_type_at(&self, type_index: u32) -> Result<&InstanceType>506 fn instance_type_at(&self, type_index: u32) -> Result<&InstanceType> {
507 if !self.features.module_linking {
508 return self.create_error("module linking proposal not enabled");
509 }
510 let ty = self.get_type(type_index)?;
511 match ty {
512 TypeDef::Instance(item) => Ok(item),
513 _ => self.create_error("type index is not an instance"),
514 }
515 }
516
check_max(&self, cur_len: usize, amt_added: u32, max: usize, desc: &str) -> Result<()>517 fn check_max(&self, cur_len: usize, amt_added: u32, max: usize, desc: &str) -> Result<()> {
518 let overflow = max
519 .checked_sub(cur_len)
520 .and_then(|amt| amt.checked_sub(amt_added as usize))
521 .is_none();
522 if overflow {
523 return if max == 1 {
524 self.create_error(format!("multiple {}", desc))
525 } else {
526 self.create_error(format!("{} count is out of bounds", desc))
527 };
528 }
529 Ok(())
530 }
531
section<T>( &mut self, order: Order, section: &T, mut validate_item: impl FnMut(&mut Self, T::Item) -> Result<()>, ) -> Result<()> where T: SectionReader + Clone + SectionWithLimitedItems,532 fn section<T>(
533 &mut self,
534 order: Order,
535 section: &T,
536 mut validate_item: impl FnMut(&mut Self, T::Item) -> Result<()>,
537 ) -> Result<()>
538 where
539 T: SectionReader + Clone + SectionWithLimitedItems,
540 {
541 self.offset = section.range().start;
542 self.update_order(order)?;
543
544 let mut section = section.clone();
545 for _ in 0..section.get_count() {
546 self.offset = section.original_position();
547 let item = section.read()?;
548 validate_item(self, item)?;
549 }
550 self.offset = section.range().end;
551 section.ensure_end()?;
552 Ok(())
553 }
554
555 /// Validates [`Payload::TypeSection`](crate::Payload)
type_section(&mut self, section: &crate::TypeSectionReader<'_>) -> Result<()>556 pub fn type_section(&mut self, section: &crate::TypeSectionReader<'_>) -> Result<()> {
557 let order = self.header_order(Order::Type);
558 self.check_max(
559 self.cur.state.types.len(),
560 section.get_count(),
561 MAX_WASM_TYPES,
562 "types",
563 )?;
564 self.section(order, section, |me, item| me.type_def(item))
565 }
566
type_def(&mut self, def: crate::TypeDef<'_>) -> Result<()>567 fn type_def(&mut self, def: crate::TypeDef<'_>) -> Result<()> {
568 let def = match def {
569 crate::TypeDef::Func(t) => {
570 for ty in t.params.iter().chain(t.returns.iter()) {
571 self.value_type(*ty)?;
572 }
573 if t.returns.len() > 1 && !self.features.multi_value {
574 return self
575 .create_error("invalid result arity: func type returns multiple values");
576 }
577 TypeDef::Func(t)
578 }
579 crate::TypeDef::Module(t) => {
580 if !self.features.module_linking {
581 return self.create_error("module linking proposal not enabled");
582 }
583 let mut imports = NameSet::default();
584 for i in t.imports.iter() {
585 let ty = self.import_entry_type(&i.ty)?;
586 imports.push(
587 self.offset,
588 i.module,
589 i.field,
590 ty,
591 &mut self.types,
592 "import",
593 )?;
594 }
595
596 let mut exports = NameSet::default();
597 for e in t.exports.iter() {
598 let ty = self.import_entry_type(&e.ty)?;
599 exports.push(self.offset, e.name, None, ty, &mut self.types, "export")?;
600 }
601 TypeDef::Module(ModuleType {
602 type_size: combine_type_sizes(
603 self.offset,
604 imports.type_size,
605 exports.type_size,
606 )?,
607 imports: imports.set,
608 exports: exports.set,
609 })
610 }
611 crate::TypeDef::Instance(t) => {
612 if !self.features.module_linking {
613 return self.create_error("module linking proposal not enabled");
614 }
615 let mut exports = NameSet::default();
616 for e in t.exports.iter() {
617 let ty = self.import_entry_type(&e.ty)?;
618 exports.push(self.offset, e.name, None, ty, &mut self.types, "export")?;
619 }
620 TypeDef::Instance(InstanceType {
621 type_size: exports.type_size,
622 exports: exports.set,
623 })
624 }
625 };
626 self.cur.state.assert_mut().types.push(self.types.len());
627 self.types.push(def);
628 Ok(())
629 }
630
value_type(&self, ty: Type) -> Result<()>631 fn value_type(&self, ty: Type) -> Result<()> {
632 match self.features.check_value_type(ty) {
633 Ok(()) => Ok(()),
634 Err(e) => self.create_error(e),
635 }
636 }
637
import_entry_type(&self, import_type: &ImportSectionEntryType) -> Result<EntityType>638 fn import_entry_type(&self, import_type: &ImportSectionEntryType) -> Result<EntityType> {
639 match import_type {
640 ImportSectionEntryType::Function(type_index) => {
641 self.func_type_at(*type_index)?;
642 Ok(EntityType::Func(self.cur.state.types[*type_index as usize]))
643 }
644 ImportSectionEntryType::Table(t) => {
645 self.table_type(t)?;
646 Ok(EntityType::Table(t.clone()))
647 }
648 ImportSectionEntryType::Memory(t) => {
649 self.memory_type(t)?;
650 Ok(EntityType::Memory(t.clone()))
651 }
652 ImportSectionEntryType::Event(t) => {
653 self.event_type(t)?;
654 Ok(EntityType::Event(
655 self.cur.state.types[t.type_index as usize],
656 ))
657 }
658 ImportSectionEntryType::Global(t) => {
659 self.global_type(t)?;
660 Ok(EntityType::Global(t.clone()))
661 }
662 ImportSectionEntryType::Module(type_index) => {
663 self.module_type_at(*type_index)?;
664 Ok(EntityType::Module(
665 self.cur.state.types[*type_index as usize],
666 ))
667 }
668 ImportSectionEntryType::Instance(type_index) => {
669 self.instance_type_at(*type_index)?;
670 Ok(EntityType::Instance(
671 self.cur.state.types[*type_index as usize],
672 ))
673 }
674 }
675 }
676
table_type(&self, ty: &TableType) -> Result<()>677 fn table_type(&self, ty: &TableType) -> Result<()> {
678 match ty.element_type {
679 Type::FuncRef => {}
680 Type::ExternRef => {
681 if !self.features.reference_types {
682 return self.create_error("element is not anyfunc");
683 }
684 }
685 _ => return self.create_error("element is not reference type"),
686 }
687 self.limits(&ty.limits)?;
688 if ty.limits.initial > MAX_WASM_TABLE_ENTRIES as u32 {
689 return self.create_error("minimum table size is out of bounds");
690 }
691 Ok(())
692 }
693
memory_type(&self, ty: &MemoryType) -> Result<()>694 fn memory_type(&self, ty: &MemoryType) -> Result<()> {
695 match ty {
696 MemoryType::M32 { limits, shared } => {
697 self.limits(limits)?;
698 let initial = limits.initial;
699 if initial as usize > MAX_WASM_MEMORY_PAGES {
700 return self.create_error("memory size must be at most 65536 pages (4GiB)");
701 }
702 if let Some(maximum) = limits.maximum {
703 if maximum as usize > MAX_WASM_MEMORY_PAGES {
704 return self.create_error("memory size must be at most 65536 pages (4GiB)");
705 }
706 }
707 if *shared {
708 if !self.features.threads {
709 return self.create_error("threads must be enabled for shared memories");
710 }
711 if limits.maximum.is_none() {
712 return self.create_error("shared memory must have maximum size");
713 }
714 }
715 }
716 MemoryType::M64 { limits, shared } => {
717 if !self.features.memory64 {
718 return self.create_error("memory64 must be enabled for 64-bit memories");
719 }
720 self.limits64(&limits)?;
721 let initial = limits.initial;
722 if initial > MAX_WASM_MEMORY64_PAGES {
723 return self.create_error("memory initial size too large");
724 }
725 if let Some(maximum) = limits.maximum {
726 if maximum > MAX_WASM_MEMORY64_PAGES {
727 return self.create_error("memory initial size too large");
728 }
729 }
730 if *shared {
731 if !self.features.threads {
732 return self.create_error("threads must be enabled for shared memories");
733 }
734 if limits.maximum.is_none() {
735 return self.create_error("shared memory must have maximum size");
736 }
737 }
738 }
739 }
740 Ok(())
741 }
742
event_type(&self, ty: &EventType) -> Result<()>743 fn event_type(&self, ty: &EventType) -> Result<()> {
744 let ty = self.func_type_at(ty.type_index)?;
745 if ty.returns.len() > 0 {
746 return self.create_error("invalid result arity for exception type");
747 }
748 Ok(())
749 }
750
global_type(&self, ty: &GlobalType) -> Result<()>751 fn global_type(&self, ty: &GlobalType) -> Result<()> {
752 self.value_type(ty.content_type)
753 }
754
limits(&self, limits: &ResizableLimits) -> Result<()>755 fn limits(&self, limits: &ResizableLimits) -> Result<()> {
756 if let Some(max) = limits.maximum {
757 if limits.initial > max {
758 return self.create_error("size minimum must not be greater than maximum");
759 }
760 }
761 Ok(())
762 }
763
limits64(&self, limits: &ResizableLimits64) -> Result<()>764 fn limits64(&self, limits: &ResizableLimits64) -> Result<()> {
765 if let Some(max) = limits.maximum {
766 if limits.initial > max {
767 return self.create_error("size minimum must not be greater than maximum");
768 }
769 }
770 Ok(())
771 }
772
773 /// Validates [`Payload::ImportSection`](crate::Payload)
import_section(&mut self, section: &crate::ImportSectionReader<'_>) -> Result<()>774 pub fn import_section(&mut self, section: &crate::ImportSectionReader<'_>) -> Result<()> {
775 let order = self.header_order(Order::Import);
776 self.section(order, section, |me, item| me.import(item))?;
777
778 // Clear the list of implicit imports after the import section is
779 // finished since later import sections cannot append further to the
780 // pseudo-instances defined in this import section.
781 self.cur.state.assert_mut().imports.implicit.drain();
782 Ok(())
783 }
784
import(&mut self, entry: Import<'_>) -> Result<()>785 fn import(&mut self, entry: Import<'_>) -> Result<()> {
786 if !self.features.module_linking && entry.field.is_none() {
787 return self.create_error("module linking proposal is not enabled");
788 }
789 let ty = self.import_entry_type(&entry.ty)?;
790 let state = self.cur.state.assert_mut();
791
792 // Build up a map of what this module imports, for when this module is a
793 // nested module it'll be needed to infer the type signature of the
794 // nested module. Note that this does not happen unless the module
795 // linking proposal is enabled.
796 //
797 // This is a breaking change! This will disallow multiple imports that
798 // import from the same item twice. We can't turn module linking
799 // on-by-default as-is without some sort of recourse for consumers that
800 // want to backwards-compatibly parse older modules still. Unclear how
801 // to do this.
802 if self.features.module_linking {
803 let implicit_instance_type = state.imports.push(
804 self.offset,
805 entry.module,
806 entry.field,
807 ty,
808 &mut self.types,
809 "import",
810 )?;
811 if let Some(idx) = implicit_instance_type {
812 state.instances.push(idx);
813 }
814 }
815 let (len, max, desc) = match entry.ty {
816 ImportSectionEntryType::Function(type_index) => {
817 let ty = state.types[type_index as usize];
818 state.func_types.push(ty);
819 (state.func_types.len(), MAX_WASM_FUNCTIONS, "funcs")
820 }
821 ImportSectionEntryType::Table(ty) => {
822 state.tables.push(ty);
823 (state.tables.len(), self.max_tables(), "tables")
824 }
825 ImportSectionEntryType::Memory(ty) => {
826 state.memories.push(ty);
827 (state.memories.len(), self.max_memories(), "memories")
828 }
829 ImportSectionEntryType::Event(ty) => {
830 let ty = state.types[ty.type_index as usize];
831 state.events.push(ty);
832 (state.events.len(), MAX_WASM_EVENTS, "events")
833 }
834 ImportSectionEntryType::Global(ty) => {
835 state.globals.push(ty);
836 (state.globals.len(), MAX_WASM_GLOBALS, "globals")
837 }
838 ImportSectionEntryType::Instance(type_idx) => {
839 let index = state.types[type_idx as usize];
840 state.instances.push(index);
841 (state.instances.len(), MAX_WASM_INSTANCES, "instances")
842 }
843 ImportSectionEntryType::Module(type_index) => {
844 let index = state.types[type_index as usize];
845 state.submodules.push(index);
846 (state.submodules.len(), MAX_WASM_MODULES, "modules")
847 }
848 };
849 self.check_max(len, 0, max, desc)?;
850 Ok(())
851 }
852
853 /// Validates [`Payload::ModuleSectionStart`](crate::Payload)
module_section_start(&mut self, count: u32, range: &Range) -> Result<()>854 pub fn module_section_start(&mut self, count: u32, range: &Range) -> Result<()> {
855 drop(count);
856 if !self.features.module_linking {
857 return self.create_error("module linking proposal not enabled");
858 }
859 self.offset = range.start;
860 self.update_order(Order::ModuleLinkingHeader)?;
861 self.check_max(
862 self.cur.state.submodules.len(),
863 count,
864 MAX_WASM_MODULES,
865 "modules",
866 )?;
867 Ok(())
868 }
869
870 /// Validates [`Payload::ModuleSectionEntry`](crate::Payload).
871 ///
872 /// Note that this does not actually perform any validation itself. The
873 /// `ModuleSectionEntry` payload is associated with a sub-parser for the
874 /// sub-module, and it's expected that the events from the [`Parser`]
875 /// are fed into this validator.
module_section_entry(&mut self)876 pub fn module_section_entry(&mut self) {
877 // Start a new module...
878 let prev = mem::replace(&mut self.cur, Module::default());
879 // ... and record the current module as its parent.
880 self.parents.push(prev);
881 }
882
883 /// Validates [`Payload::AliasSection`](crate::Payload)
alias_section(&mut self, section: &crate::AliasSectionReader<'_>) -> Result<()>884 pub fn alias_section(&mut self, section: &crate::AliasSectionReader<'_>) -> Result<()> {
885 if !self.features.module_linking {
886 return self.create_error("module linking proposal not enabled");
887 }
888 self.section(Order::ModuleLinkingHeader, section, |me, a| me.alias(a))
889 }
890
alias(&mut self, alias: Alias) -> Result<()>891 fn alias(&mut self, alias: Alias) -> Result<()> {
892 match alias {
893 Alias::InstanceExport {
894 instance,
895 kind,
896 export,
897 } => {
898 let ty = self.get_instance_type(instance)?;
899 let export = match ty.exports.get(export) {
900 Some(e) => e,
901 None => {
902 return self.create_error(format!(
903 "aliased name `{}` does not exist in instance",
904 export
905 ));
906 }
907 };
908 match (export, kind) {
909 (EntityType::Func(ty), ExternalKind::Function) => {
910 let ty = *ty;
911 self.cur.state.assert_mut().func_types.push(ty);
912 }
913 (EntityType::Table(ty), ExternalKind::Table) => {
914 let ty = ty.clone();
915 self.cur.state.assert_mut().tables.push(ty);
916 }
917 (EntityType::Memory(ty), ExternalKind::Memory) => {
918 let ty = ty.clone();
919 self.cur.state.assert_mut().memories.push(ty);
920 }
921 (EntityType::Event(ty), ExternalKind::Event) => {
922 let ty = *ty;
923 self.cur.state.assert_mut().events.push(ty);
924 }
925 (EntityType::Global(ty), ExternalKind::Global) => {
926 let ty = ty.clone();
927 self.cur.state.assert_mut().globals.push(ty);
928 }
929 (EntityType::Instance(ty), ExternalKind::Instance) => {
930 let ty = *ty;
931 self.cur.state.assert_mut().instances.push(ty);
932 }
933 (EntityType::Module(ty), ExternalKind::Module) => {
934 let ty = *ty;
935 self.cur.state.assert_mut().submodules.push(ty);
936 }
937 _ => return self.create_error("alias kind mismatch with export kind"),
938 }
939 }
940 Alias::OuterType {
941 relative_depth,
942 index,
943 } => {
944 let i = self
945 .parents
946 .len()
947 .checked_sub(relative_depth as usize)
948 .and_then(|i| i.checked_sub(1))
949 .ok_or_else(|| {
950 BinaryReaderError::new("relative depth too large", self.offset)
951 })?;
952 let ty = match self.parents[i].state.types.get(index as usize) {
953 Some(m) => *m,
954 None => return self.create_error("alias to type not defined in parent yet"),
955 };
956 self.cur.state.assert_mut().types.push(ty);
957 }
958 Alias::OuterModule {
959 relative_depth,
960 index,
961 } => {
962 let i = self
963 .parents
964 .len()
965 .checked_sub(relative_depth as usize)
966 .and_then(|i| i.checked_sub(1))
967 .ok_or_else(|| {
968 BinaryReaderError::new("relative depth too large", self.offset)
969 })?;
970 let module = match self.parents[i].state.submodules.get(index as usize) {
971 Some(m) => *m,
972 None => return self.create_error("alias to module not defined in parent yet"),
973 };
974 self.cur.state.assert_mut().submodules.push(module);
975 }
976 }
977
978 Ok(())
979 }
980
981 /// Validates [`Payload::InstanceSection`](crate::Payload)
instance_section(&mut self, section: &crate::InstanceSectionReader<'_>) -> Result<()>982 pub fn instance_section(&mut self, section: &crate::InstanceSectionReader<'_>) -> Result<()> {
983 if !self.features.module_linking {
984 return self.create_error("module linking proposal not enabled");
985 }
986 self.check_max(
987 self.cur.state.instances.len(),
988 section.get_count(),
989 MAX_WASM_INSTANCES,
990 "instances",
991 )?;
992 self.section(Order::ModuleLinkingHeader, section, |me, i| me.instance(i))
993 }
994
instance(&mut self, instance: Instance<'_>) -> Result<()>995 fn instance(&mut self, instance: Instance<'_>) -> Result<()> {
996 // Fetch the type of the instantiated module so we can typecheck all of
997 // the import items.
998 let module_idx = instance.module();
999
1000 // Build up the set of what we're providing as imports.
1001 let mut set = NameSet::default();
1002 for arg in instance.args()? {
1003 let arg = arg?;
1004 let ty = self.check_external_kind("instance argument", arg.kind, arg.index)?;
1005 set.push(self.offset, arg.name, None, ty, &mut self.types, "arg")?;
1006 }
1007
1008 // Check our provided `set` to ensure it's a subtype of the expected set
1009 // of imports from the module's import types.
1010 let ty = self.get_module_type(module_idx)?;
1011 self.check_type_sets_match(&set.set, &ty.imports, "import")?;
1012
1013 // Create a synthetic type declaration for this instance's type and
1014 // record its type in the global type list. We might not have another
1015 // `TypeDef::Instance` to point to if the module was locally declared.
1016 //
1017 // Note that the predicted size of this type is inflated due to
1018 // accounting for the imports on the original module, but that should be
1019 // ok for now since it's only used to limit the size of larger types.
1020 let instance_ty = InstanceType {
1021 type_size: ty.type_size,
1022 exports: ty.exports.clone(),
1023 };
1024 self.cur.state.assert_mut().instances.push(self.types.len());
1025 self.types.push(TypeDef::Instance(instance_ty));
1026 Ok(())
1027 }
1028
1029 // Note that this function is basically implementing
1030 // https://webassembly.github.io/spec/core/exec/modules.html#import-matching
check_subtypes(&self, a: &EntityType, b: &EntityType) -> Result<()>1031 fn check_subtypes(&self, a: &EntityType, b: &EntityType) -> Result<()> {
1032 macro_rules! limits_match {
1033 ($a:expr, $b:expr) => {{
1034 let a = $a;
1035 let b = $b;
1036 a.initial >= b.initial
1037 && match b.maximum {
1038 Some(b_max) => match a.maximum {
1039 Some(a_max) => a_max <= b_max,
1040 None => false,
1041 },
1042 None => true,
1043 }
1044 }};
1045 }
1046 match a {
1047 EntityType::Global(a) => {
1048 let b = match b {
1049 EntityType::Global(b) => b,
1050 _ => return self.create_error("item type mismatch"),
1051 };
1052 if a == b {
1053 Ok(())
1054 } else {
1055 self.create_error("global type mismatch")
1056 }
1057 }
1058 EntityType::Table(a) => {
1059 let b = match b {
1060 EntityType::Table(b) => b,
1061 _ => return self.create_error("item type mismatch"),
1062 };
1063 if a.element_type == b.element_type && limits_match!(&a.limits, &b.limits) {
1064 Ok(())
1065 } else {
1066 self.create_error("table type mismatch")
1067 }
1068 }
1069 EntityType::Func(a) => {
1070 let b = match b {
1071 EntityType::Func(b) => b,
1072 _ => return self.create_error("item type mismatch"),
1073 };
1074 if self.types[*a].unwrap_func() == self.types[*b].unwrap_func() {
1075 Ok(())
1076 } else {
1077 self.create_error("func type mismatch")
1078 }
1079 }
1080 EntityType::Event(a) => {
1081 let b = match b {
1082 EntityType::Event(b) => b,
1083 _ => return self.create_error("item type mismatch"),
1084 };
1085 if self.types[*a].unwrap_func() == self.types[*b].unwrap_func() {
1086 Ok(())
1087 } else {
1088 self.create_error("event type mismatch")
1089 }
1090 }
1091 EntityType::Memory(MemoryType::M32 { limits, shared }) => {
1092 let (b_limits, b_shared) = match b {
1093 EntityType::Memory(MemoryType::M32 { limits, shared }) => (limits, shared),
1094 _ => return self.create_error("item type mismatch"),
1095 };
1096 if limits_match!(limits, b_limits) && shared == b_shared {
1097 Ok(())
1098 } else {
1099 self.create_error("memory type mismatch")
1100 }
1101 }
1102 EntityType::Memory(MemoryType::M64 { limits, shared }) => {
1103 let (b_limits, b_shared) = match b {
1104 EntityType::Memory(MemoryType::M64 { limits, shared }) => (limits, shared),
1105 _ => return self.create_error("item type mismatch"),
1106 };
1107 if limits_match!(limits, b_limits) && shared == b_shared {
1108 Ok(())
1109 } else {
1110 self.create_error("memory type mismatch")
1111 }
1112 }
1113 EntityType::Instance(a) => {
1114 let b = match b {
1115 EntityType::Instance(b) => b,
1116 _ => return self.create_error("item type mismatch"),
1117 };
1118 let a = self.types[*a].unwrap_instance();
1119 let b = self.types[*b].unwrap_instance();
1120 self.check_type_sets_match(&a.exports, &b.exports, "export")?;
1121 Ok(())
1122 }
1123 EntityType::Module(a) => {
1124 let b = match b {
1125 EntityType::Module(b) => b,
1126 _ => return self.create_error("item type mismatch"),
1127 };
1128 let a = self.types[*a].unwrap_module();
1129 let b = self.types[*b].unwrap_module();
1130 // Note the order changing between imports and exports! This is
1131 // a live demonstration of variance in action.
1132 self.check_type_sets_match(&b.imports, &a.imports, "import")?;
1133 self.check_type_sets_match(&a.exports, &b.exports, "export")?;
1134 Ok(())
1135 }
1136 }
1137 }
1138
check_type_sets_match( &self, a: &HashMap<String, EntityType>, b: &HashMap<String, EntityType>, desc: &str, ) -> Result<()>1139 fn check_type_sets_match(
1140 &self,
1141 a: &HashMap<String, EntityType>,
1142 b: &HashMap<String, EntityType>,
1143 desc: &str,
1144 ) -> Result<()> {
1145 for (name, b) in b {
1146 match a.get(name) {
1147 Some(a) => self.check_subtypes(a, b)?,
1148 None => return self.create_error(&format!("no {} named `{}`", desc, name)),
1149 }
1150 }
1151 Ok(())
1152 }
1153
1154 /// Validates [`Payload::FunctionSection`](crate::Payload)
function_section(&mut self, section: &crate::FunctionSectionReader<'_>) -> Result<()>1155 pub fn function_section(&mut self, section: &crate::FunctionSectionReader<'_>) -> Result<()> {
1156 self.cur.expected_code_bodies = Some(section.get_count());
1157 self.check_max(
1158 self.cur.state.func_types.len(),
1159 section.get_count(),
1160 MAX_WASM_FUNCTIONS,
1161 "funcs",
1162 )?;
1163 // Assert that each type index is indeed a function type, and otherwise
1164 // just push it for handling later.
1165 self.section(Order::Function, section, |me, i| {
1166 me.func_type_at(i)?;
1167 let state = me.cur.state.assert_mut();
1168 state.func_types.push(state.types[i as usize]);
1169 state.code_type_indexes.push(i);
1170 Ok(())
1171 })
1172 }
1173
max_tables(&self) -> usize1174 fn max_tables(&self) -> usize {
1175 if self.features.reference_types || self.features.module_linking {
1176 MAX_WASM_TABLES
1177 } else {
1178 1
1179 }
1180 }
1181
1182 /// Validates [`Payload::TableSection`](crate::Payload)
table_section(&mut self, section: &crate::TableSectionReader<'_>) -> Result<()>1183 pub fn table_section(&mut self, section: &crate::TableSectionReader<'_>) -> Result<()> {
1184 self.check_max(
1185 self.cur.state.tables.len(),
1186 section.get_count(),
1187 self.max_tables(),
1188 "tables",
1189 )?;
1190 self.section(Order::Table, section, |me, ty| {
1191 me.table_type(&ty)?;
1192 me.cur.state.assert_mut().tables.push(ty);
1193 Ok(())
1194 })
1195 }
1196
max_memories(&self) -> usize1197 fn max_memories(&self) -> usize {
1198 if self.features.multi_memory {
1199 MAX_WASM_MEMORIES
1200 } else {
1201 1
1202 }
1203 }
1204
memory_section(&mut self, section: &crate::MemorySectionReader<'_>) -> Result<()>1205 pub fn memory_section(&mut self, section: &crate::MemorySectionReader<'_>) -> Result<()> {
1206 self.check_max(
1207 self.cur.state.memories.len(),
1208 section.get_count(),
1209 self.max_memories(),
1210 "memories",
1211 )?;
1212 self.section(Order::Memory, section, |me, ty| {
1213 me.memory_type(&ty)?;
1214 me.cur.state.assert_mut().memories.push(ty);
1215 Ok(())
1216 })
1217 }
1218
event_section(&mut self, section: &crate::EventSectionReader<'_>) -> Result<()>1219 pub fn event_section(&mut self, section: &crate::EventSectionReader<'_>) -> Result<()> {
1220 self.check_max(
1221 self.cur.state.events.len(),
1222 section.get_count(),
1223 MAX_WASM_EVENTS,
1224 "events",
1225 )?;
1226 self.section(Order::Event, section, |me, ty| {
1227 me.event_type(&ty)?;
1228 let state = me.cur.state.assert_mut();
1229 state.events.push(state.types[ty.type_index as usize]);
1230 Ok(())
1231 })
1232 }
1233
1234 /// Validates [`Payload::GlobalSection`](crate::Payload)
global_section(&mut self, section: &crate::GlobalSectionReader<'_>) -> Result<()>1235 pub fn global_section(&mut self, section: &crate::GlobalSectionReader<'_>) -> Result<()> {
1236 self.check_max(
1237 self.cur.state.globals.len(),
1238 section.get_count(),
1239 MAX_WASM_GLOBALS,
1240 "globals",
1241 )?;
1242 self.section(Order::Global, section, |me, g| {
1243 me.global_type(&g.ty)?;
1244 me.init_expr(&g.init_expr, g.ty.content_type)?;
1245 me.cur.state.assert_mut().globals.push(g.ty);
1246 Ok(())
1247 })
1248 }
1249
init_expr(&mut self, expr: &InitExpr<'_>, expected_ty: Type) -> Result<()>1250 fn init_expr(&mut self, expr: &InitExpr<'_>, expected_ty: Type) -> Result<()> {
1251 let mut ops = expr.get_operators_reader().into_iter_with_offsets();
1252 let (op, offset) = match ops.next() {
1253 Some(Err(e)) => return Err(e),
1254 Some(Ok(pair)) => pair,
1255 None => return self.create_error("type mismatch: init_expr is empty"),
1256 };
1257 self.offset = offset;
1258 let mut function_reference = None;
1259 let ty = match op {
1260 Operator::I32Const { .. } => Type::I32,
1261 Operator::I64Const { .. } => Type::I64,
1262 Operator::F32Const { .. } => Type::F32,
1263 Operator::F64Const { .. } => Type::F64,
1264 Operator::RefNull { ty } => ty,
1265 Operator::V128Const { .. } => Type::V128,
1266 Operator::GlobalGet { global_index } => {
1267 let global = self.get_global(global_index)?;
1268 if global.mutable {
1269 return self.create_error(
1270 "constant expression required: global.get of mutable global",
1271 );
1272 }
1273 global.content_type
1274 }
1275 Operator::RefFunc { function_index } => {
1276 function_reference = Some(function_index);
1277 self.get_func_type(function_index)?;
1278 Type::FuncRef
1279 }
1280 Operator::End => return self.create_error("type mismatch: init_expr is empty"),
1281 _ => {
1282 return self
1283 .create_error("constant expression required: invalid init_expr operator")
1284 }
1285 };
1286 if ty != expected_ty {
1287 return self.create_error("type mismatch: invalid init_expr type");
1288 }
1289
1290 if let Some(index) = function_reference {
1291 self.cur
1292 .state
1293 .assert_mut()
1294 .function_references
1295 .insert(index);
1296 }
1297
1298 // Make sure the next instruction is an `end`
1299 match ops.next() {
1300 Some(Err(e)) => return Err(e),
1301 Some(Ok((Operator::End, _))) => {}
1302 Some(Ok(_)) => {
1303 return self
1304 .create_error("constant expression required: type mismatch: only one init_expr operator is expected")
1305 }
1306 None => return self.create_error("type mismatch: init_expr is not terminated"),
1307 }
1308
1309 // ... and verify we're done after that
1310 match ops.next() {
1311 Some(Err(e)) => Err(e),
1312 Some(Ok(_)) => {
1313 self.create_error("constant expression required: invalid init_expr operator")
1314 }
1315 None => Ok(()),
1316 }
1317 }
1318
1319 /// Validates [`Payload::ExportSection`](crate::Payload)
export_section(&mut self, section: &crate::ExportSectionReader<'_>) -> Result<()>1320 pub fn export_section(&mut self, section: &crate::ExportSectionReader<'_>) -> Result<()> {
1321 self.section(Order::Export, section, |me, e| {
1322 if let ExternalKind::Type = e.kind {
1323 return me.create_error("cannot export types");
1324 }
1325 let ty = me.check_external_kind("exported", e.kind, e.index)?;
1326 let state = me.cur.state.assert_mut();
1327 state
1328 .exports
1329 .push(me.offset, e.field, None, ty, &mut me.types, "export")?;
1330 Ok(())
1331 })
1332 }
1333
check_external_kind( &mut self, desc: &str, kind: ExternalKind, index: u32, ) -> Result<EntityType>1334 fn check_external_kind(
1335 &mut self,
1336 desc: &str,
1337 kind: ExternalKind,
1338 index: u32,
1339 ) -> Result<EntityType> {
1340 let check = |ty: &str, total: usize| {
1341 if index as usize >= total {
1342 self.create_error(&format!(
1343 "unknown {ty} {index}: {desc} {ty} index out of bounds",
1344 desc = desc,
1345 index = index,
1346 ty = ty,
1347 ))
1348 } else {
1349 Ok(())
1350 }
1351 };
1352 Ok(match kind {
1353 ExternalKind::Function => {
1354 check("function", self.cur.state.func_types.len())?;
1355 self.cur
1356 .state
1357 .assert_mut()
1358 .function_references
1359 .insert(index);
1360 EntityType::Func(self.cur.state.func_types[index as usize])
1361 }
1362 ExternalKind::Table => {
1363 check("table", self.cur.state.tables.len())?;
1364 EntityType::Table(self.cur.state.tables[index as usize].clone())
1365 }
1366 ExternalKind::Memory => {
1367 check("memory", self.cur.state.memories.len())?;
1368 EntityType::Memory(self.cur.state.memories[index as usize].clone())
1369 }
1370 ExternalKind::Global => {
1371 check("global", self.cur.state.globals.len())?;
1372 EntityType::Global(self.cur.state.globals[index as usize].clone())
1373 }
1374 ExternalKind::Event => {
1375 check("event", self.cur.state.events.len())?;
1376 EntityType::Event(self.cur.state.events[index as usize])
1377 }
1378 ExternalKind::Module => {
1379 check("module", self.cur.state.submodules.len())?;
1380 EntityType::Module(self.cur.state.submodules[index as usize])
1381 }
1382 ExternalKind::Instance => {
1383 check("instance", self.cur.state.instances.len())?;
1384 EntityType::Instance(self.cur.state.instances[index as usize])
1385 }
1386 ExternalKind::Type => return self.create_error("cannot export types"),
1387 })
1388 }
1389
1390 /// Validates [`Payload::StartSection`](crate::Payload)
start_section(&mut self, func: u32, range: &Range) -> Result<()>1391 pub fn start_section(&mut self, func: u32, range: &Range) -> Result<()> {
1392 self.offset = range.start;
1393 self.update_order(Order::Start)?;
1394 let ty = self.get_func_type(func)?;
1395 if !ty.params.is_empty() || !ty.returns.is_empty() {
1396 return self.create_error("invalid start function type");
1397 }
1398 Ok(())
1399 }
1400
1401 /// Validates [`Payload::ElementSection`](crate::Payload)
element_section(&mut self, section: &crate::ElementSectionReader<'_>) -> Result<()>1402 pub fn element_section(&mut self, section: &crate::ElementSectionReader<'_>) -> Result<()> {
1403 self.section(Order::Element, section, |me, e| {
1404 match e.ty {
1405 Type::FuncRef => {}
1406 Type::ExternRef if me.features.reference_types => {}
1407 Type::ExternRef => {
1408 return me
1409 .create_error("reference types must be enabled for anyref elem segment");
1410 }
1411 _ => return me.create_error("invalid reference type"),
1412 }
1413 match e.kind {
1414 ElementKind::Active {
1415 table_index,
1416 init_expr,
1417 } => {
1418 let table = me.get_table(table_index)?;
1419 if e.ty != table.element_type {
1420 return me.create_error("element_type != table type");
1421 }
1422 me.init_expr(&init_expr, Type::I32)?;
1423 }
1424 ElementKind::Passive | ElementKind::Declared => {
1425 if !me.features.bulk_memory {
1426 return me.create_error("reference types must be enabled");
1427 }
1428 }
1429 }
1430 let mut items = e.items.get_items_reader()?;
1431 if items.get_count() > MAX_WASM_TABLE_ENTRIES as u32 {
1432 return me.create_error("num_elements is out of bounds");
1433 }
1434 for _ in 0..items.get_count() {
1435 me.offset = items.original_position();
1436 match items.read()? {
1437 ElementItem::Null(ty) => {
1438 if ty != e.ty {
1439 return me.create_error(
1440 "type mismatch: null type doesn't match element type",
1441 );
1442 }
1443 }
1444 ElementItem::Func(f) => {
1445 if e.ty != Type::FuncRef {
1446 return me
1447 .create_error("type mismatch: segment does not have funcref type");
1448 }
1449 me.get_func_type(f)?;
1450 me.cur.state.assert_mut().function_references.insert(f);
1451 }
1452 }
1453 }
1454
1455 me.cur.state.assert_mut().element_types.push(e.ty);
1456 Ok(())
1457 })
1458 }
1459
1460 /// Validates [`Payload::DataCountSection`](crate::Payload)
data_count_section(&mut self, count: u32, range: &Range) -> Result<()>1461 pub fn data_count_section(&mut self, count: u32, range: &Range) -> Result<()> {
1462 self.offset = range.start;
1463 self.update_order(Order::DataCount)?;
1464 self.cur.state.assert_mut().data_count = Some(count);
1465 if count > MAX_WASM_DATA_SEGMENTS as u32 {
1466 return self.create_error("data count section specifies too many data segments");
1467 }
1468 Ok(())
1469 }
1470
1471 /// Validates [`Payload::CodeSectionStart`](crate::Payload).
code_section_start(&mut self, count: u32, range: &Range) -> Result<()>1472 pub fn code_section_start(&mut self, count: u32, range: &Range) -> Result<()> {
1473 self.offset = range.start;
1474 self.update_order(Order::Code)?;
1475 match self.cur.expected_code_bodies.take() {
1476 Some(n) if n == count => {}
1477 Some(_) => {
1478 return self.create_error("function and code section have inconsistent lengths");
1479 }
1480 // empty code sections are allowed even if the function section is
1481 // missing
1482 None if count == 0 => {}
1483 None => return self.create_error("code section without function section"),
1484 }
1485
1486 // Prepare our module's view into the global `types` array. This enables
1487 // parallel function validation to accesss our built-so-far list off
1488 // types. Note that all the `WasmModuleResources` methods rely on
1489 // `all_types` being filled in, and this is the point at which they're
1490 // filled in.
1491 let types = self.types.commit();
1492 self.cur.state.assert_mut().all_types = Some(Arc::new(types));
1493
1494 Ok(())
1495 }
1496
1497 /// Validates [`Payload::CodeSectionEntry`](crate::Payload).
1498 ///
1499 /// This function will prepare a [`FuncValidator`] which can be used to
1500 /// validate the function. The function body provided will be parsed only
1501 /// enough to create the function validation context. After this the
1502 /// [`OperatorsReader`](crate::readers::OperatorsReader) returned can be used to read the
1503 /// opcodes of the function as well as feed information into the validator.
1504 ///
1505 /// Note that the returned [`FuncValidator`] is "connected" to this
1506 /// [`Validator`] in that it uses the internal context of this validator for
1507 /// validating the function. The [`FuncValidator`] can be sent to
1508 /// another thread, for example, to offload actual processing of functions
1509 /// elsewhere.
code_section_entry(&mut self) -> Result<FuncValidator<ValidatorResources>>1510 pub fn code_section_entry(&mut self) -> Result<FuncValidator<ValidatorResources>> {
1511 let ty = self.cur.state.code_type_indexes[self.cur.code_section_index];
1512 self.cur.code_section_index += 1;
1513 let resources = ValidatorResources(self.cur.state.arc().clone());
1514 Ok(FuncValidator::new(ty, 0, resources, &self.features).unwrap())
1515 }
1516
1517 /// Validates [`Payload::DataSection`](crate::Payload).
data_section(&mut self, section: &crate::DataSectionReader<'_>) -> Result<()>1518 pub fn data_section(&mut self, section: &crate::DataSectionReader<'_>) -> Result<()> {
1519 self.cur.data_found = section.get_count();
1520 self.check_max(0, section.get_count(), MAX_WASM_DATA_SEGMENTS, "segments")?;
1521 let mut section = section.clone();
1522 section.forbid_bulk_memory(!self.features.bulk_memory);
1523 self.section(Order::Data, §ion, |me, d| {
1524 match d.kind {
1525 DataKind::Passive => {}
1526 DataKind::Active {
1527 memory_index,
1528 init_expr,
1529 } => {
1530 let ty = me.get_memory(memory_index)?.index_type();
1531 me.init_expr(&init_expr, ty)?;
1532 }
1533 }
1534 Ok(())
1535 })
1536 }
1537
1538 /// Validates [`Payload::UnknownSection`](crate::Payload).
1539 ///
1540 /// Currently always returns an error.
unknown_section(&mut self, id: u8, range: &Range) -> Result<()>1541 pub fn unknown_section(&mut self, id: u8, range: &Range) -> Result<()> {
1542 self.offset = range.start;
1543 self.create_error(format!("invalid section code: {}", id))
1544 }
1545
1546 /// Validates [`Payload::End`](crate::Payload).
end(&mut self) -> Result<()>1547 pub fn end(&mut self) -> Result<()> {
1548 // Ensure that the data count section, if any, was correct.
1549 if let Some(data_count) = self.cur.state.data_count {
1550 if data_count != self.cur.data_found {
1551 return self.create_error("data count section and passive data mismatch");
1552 }
1553 }
1554 // Ensure that the function section, if nonzero, was paired with a code
1555 // section with the appropriate length.
1556 if let Some(n) = self.cur.expected_code_bodies.take() {
1557 if n > 0 {
1558 return self.create_error("function and code sections have inconsistent lengths");
1559 }
1560 }
1561
1562 // Ensure that the effective type size of this module is of a bounded
1563 // size. This is primarily here for the module linking proposal, and
1564 // we'll record this in the module type below if we're part of a nested
1565 // module.
1566 let type_size = combine_type_sizes(
1567 self.offset,
1568 self.cur.state.imports.type_size,
1569 self.cur.state.exports.type_size,
1570 )?;
1571
1572 // If we have a parent then we're going to exit this module's context
1573 // and resume where we left off in the parent. We inject a new type for
1574 // our module we just validated in the parent's module index space, and
1575 // then we reset our current state to the parent.
1576 if let Some(mut parent) = self.parents.pop() {
1577 let module_type = self.types.len();
1578 self.types.push(TypeDef::Module(ModuleType {
1579 type_size,
1580 imports: self.cur.state.imports.set.clone(),
1581 exports: self.cur.state.exports.set.clone(),
1582 }));
1583 parent.state.assert_mut().submodules.push(module_type);
1584 self.cur = parent;
1585 }
1586 Ok(())
1587 }
1588 }
1589
1590 impl WasmModuleResources for Validator {
1591 type FuncType = crate::FuncType;
1592
table_at(&self, at: u32) -> Option<TableType>1593 fn table_at(&self, at: u32) -> Option<TableType> {
1594 self.cur.state.table_at(at)
1595 }
1596
memory_at(&self, at: u32) -> Option<MemoryType>1597 fn memory_at(&self, at: u32) -> Option<MemoryType> {
1598 self.cur.state.memory_at(at)
1599 }
1600
event_at(&self, at: u32) -> Option<&Self::FuncType>1601 fn event_at(&self, at: u32) -> Option<&Self::FuncType> {
1602 self.cur.state.event_at(at)
1603 }
1604
global_at(&self, at: u32) -> Option<GlobalType>1605 fn global_at(&self, at: u32) -> Option<GlobalType> {
1606 self.cur.state.global_at(at)
1607 }
1608
func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType>1609 fn func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType> {
1610 self.cur.state.func_type_at(type_idx)
1611 }
1612
type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType>1613 fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
1614 self.cur.state.type_of_function(func_idx)
1615 }
1616
element_type_at(&self, at: u32) -> Option<Type>1617 fn element_type_at(&self, at: u32) -> Option<Type> {
1618 self.cur.state.element_type_at(at)
1619 }
1620
element_count(&self) -> u321621 fn element_count(&self) -> u32 {
1622 self.cur.state.element_count()
1623 }
1624
data_count(&self) -> u321625 fn data_count(&self) -> u32 {
1626 self.cur.state.data_count()
1627 }
1628
is_function_referenced(&self, idx: u32) -> bool1629 fn is_function_referenced(&self, idx: u32) -> bool {
1630 self.cur.state.is_function_referenced(idx)
1631 }
1632 }
1633
combine_type_sizes(offset: usize, a: u32, b: u32) -> Result<u32>1634 fn combine_type_sizes(offset: usize, a: u32, b: u32) -> Result<u32> {
1635 match a.checked_add(b) {
1636 Some(sum) if sum < MAX_TYPE_SIZE => Ok(sum),
1637 _ => Err(BinaryReaderError::new(
1638 "effective type size too large".to_string(),
1639 offset,
1640 )),
1641 }
1642 }
1643
1644 impl WasmFeatures {
check_value_type(&self, ty: Type) -> Result<(), &'static str>1645 pub(crate) fn check_value_type(&self, ty: Type) -> Result<(), &'static str> {
1646 match ty {
1647 Type::I32 | Type::I64 | Type::F32 | Type::F64 => Ok(()),
1648 Type::FuncRef | Type::ExternRef => {
1649 if self.reference_types {
1650 Ok(())
1651 } else {
1652 Err("reference types support is not enabled")
1653 }
1654 }
1655 Type::ExnRef => {
1656 if self.exceptions {
1657 Ok(())
1658 } else {
1659 Err("exceptions support is not enabled")
1660 }
1661 }
1662 Type::V128 => {
1663 if self.simd {
1664 Ok(())
1665 } else {
1666 Err("SIMD support is not enabled")
1667 }
1668 }
1669 _ => Err("invalid value type"),
1670 }
1671 }
1672 }
1673
1674 impl WasmModuleResources for ModuleState {
1675 type FuncType = crate::FuncType;
1676
table_at(&self, at: u32) -> Option<TableType>1677 fn table_at(&self, at: u32) -> Option<TableType> {
1678 self.tables.get(at as usize).cloned()
1679 }
1680
memory_at(&self, at: u32) -> Option<MemoryType>1681 fn memory_at(&self, at: u32) -> Option<MemoryType> {
1682 self.memories.get(at as usize).cloned()
1683 }
1684
event_at(&self, at: u32) -> Option<&Self::FuncType>1685 fn event_at(&self, at: u32) -> Option<&Self::FuncType> {
1686 let types = self.all_types.as_ref().unwrap();
1687 let i = *self.events.get(at as usize)?;
1688 match &types[i] {
1689 TypeDef::Func(f) => Some(f),
1690 _ => None,
1691 }
1692 }
1693
global_at(&self, at: u32) -> Option<GlobalType>1694 fn global_at(&self, at: u32) -> Option<GlobalType> {
1695 self.globals.get(at as usize).cloned()
1696 }
1697
func_type_at(&self, at: u32) -> Option<&Self::FuncType>1698 fn func_type_at(&self, at: u32) -> Option<&Self::FuncType> {
1699 let types = self.all_types.as_ref().unwrap();
1700 let i = *self.types.get(at as usize)?;
1701 match &types[i] {
1702 TypeDef::Func(f) => Some(f),
1703 _ => None,
1704 }
1705 }
1706
type_of_function(&self, at: u32) -> Option<&Self::FuncType>1707 fn type_of_function(&self, at: u32) -> Option<&Self::FuncType> {
1708 let types = self.all_types.as_ref().unwrap();
1709 let i = *self.func_types.get(at as usize)?;
1710 match &types[i] {
1711 TypeDef::Func(f) => Some(f),
1712 _ => None,
1713 }
1714 }
1715
element_type_at(&self, at: u32) -> Option<Type>1716 fn element_type_at(&self, at: u32) -> Option<Type> {
1717 self.element_types.get(at as usize).cloned()
1718 }
1719
element_count(&self) -> u321720 fn element_count(&self) -> u32 {
1721 self.element_types.len() as u32
1722 }
1723
data_count(&self) -> u321724 fn data_count(&self) -> u32 {
1725 self.data_count.unwrap_or(0)
1726 }
1727
is_function_referenced(&self, idx: u32) -> bool1728 fn is_function_referenced(&self, idx: u32) -> bool {
1729 self.function_references.contains(&idx)
1730 }
1731 }
1732
1733 /// The implementation of [`WasmModuleResources`] used by [`Validator`].
1734 pub struct ValidatorResources(Arc<ModuleState>);
1735
1736 impl WasmModuleResources for ValidatorResources {
1737 type FuncType = crate::FuncType;
1738
table_at(&self, at: u32) -> Option<TableType>1739 fn table_at(&self, at: u32) -> Option<TableType> {
1740 self.0.table_at(at)
1741 }
1742
memory_at(&self, at: u32) -> Option<MemoryType>1743 fn memory_at(&self, at: u32) -> Option<MemoryType> {
1744 self.0.memory_at(at)
1745 }
1746
event_at(&self, at: u32) -> Option<&Self::FuncType>1747 fn event_at(&self, at: u32) -> Option<&Self::FuncType> {
1748 self.0.event_at(at)
1749 }
1750
global_at(&self, at: u32) -> Option<GlobalType>1751 fn global_at(&self, at: u32) -> Option<GlobalType> {
1752 self.0.global_at(at)
1753 }
1754
func_type_at(&self, at: u32) -> Option<&Self::FuncType>1755 fn func_type_at(&self, at: u32) -> Option<&Self::FuncType> {
1756 self.0.func_type_at(at)
1757 }
1758
type_of_function(&self, at: u32) -> Option<&Self::FuncType>1759 fn type_of_function(&self, at: u32) -> Option<&Self::FuncType> {
1760 self.0.type_of_function(at)
1761 }
1762
element_type_at(&self, at: u32) -> Option<Type>1763 fn element_type_at(&self, at: u32) -> Option<Type> {
1764 self.0.element_type_at(at)
1765 }
1766
element_count(&self) -> u321767 fn element_count(&self) -> u32 {
1768 self.0.element_count()
1769 }
1770
data_count(&self) -> u321771 fn data_count(&self) -> u32 {
1772 self.0.data_count()
1773 }
1774
is_function_referenced(&self, idx: u32) -> bool1775 fn is_function_referenced(&self, idx: u32) -> bool {
1776 self.0.is_function_referenced(idx)
1777 }
1778 }
1779
1780 mod arc {
1781 use std::ops::Deref;
1782 use std::sync::Arc;
1783
1784 pub struct MaybeOwned<T> {
1785 owned: bool,
1786 arc: Arc<T>,
1787 }
1788
1789 impl<T> MaybeOwned<T> {
as_mut(&mut self) -> Option<&mut T>1790 pub fn as_mut(&mut self) -> Option<&mut T> {
1791 if !self.owned {
1792 return None;
1793 }
1794 debug_assert!(Arc::get_mut(&mut self.arc).is_some());
1795 Some(unsafe { &mut *(&*self.arc as *const T as *mut T) })
1796 }
1797
assert_mut(&mut self) -> &mut T1798 pub fn assert_mut(&mut self) -> &mut T {
1799 self.as_mut().unwrap()
1800 }
1801
arc(&mut self) -> &Arc<T>1802 pub fn arc(&mut self) -> &Arc<T> {
1803 self.owned = false;
1804 &self.arc
1805 }
1806 }
1807
1808 impl<T: Default> Default for MaybeOwned<T> {
default() -> MaybeOwned<T>1809 fn default() -> MaybeOwned<T> {
1810 MaybeOwned {
1811 owned: true,
1812 arc: Arc::default(),
1813 }
1814 }
1815 }
1816
1817 impl<T> Deref for MaybeOwned<T> {
1818 type Target = T;
1819
deref(&self) -> &T1820 fn deref(&self) -> &T {
1821 &self.arc
1822 }
1823 }
1824 }
1825
1826 /// This is a helper structure to create a map from names to types.
1827 ///
1828 /// The main purpose of this structure is to handle the two-level imports found
1829 /// in wasm modules pre-module-linking. A two-level import is equivalent to a
1830 /// single-level import of an instance, and that mapping happens here.
1831 #[derive(Default)]
1832 struct NameSet {
1833 set: HashMap<String, EntityType>,
1834 implicit: HashSet<String>,
1835 type_size: u32,
1836 }
1837
1838 impl NameSet {
1839 /// Pushes a new name into this typed set off names, internally handling the
1840 /// mapping of two-level namespaces into a single-level namespace.
1841 ///
1842 /// * `offset` - the binary offset in the original wasm file of where to
1843 /// report errors about.
1844 /// * `module` - the first-level name in the namespace
1845 /// * `name` - the optional second-level namespace
1846 /// * `ty` - the type of the item being pushed
1847 /// * `types` - our global list of types
1848 /// * `desc` - a human-readable description of the item being pushed, used
1849 /// for generating errors.
1850 ///
1851 /// Returns an error if the name was a duplicate. Returns `Ok(Some(idx))` if
1852 /// this push was the first push to define an implicit instance with the
1853 /// type `idx` into the global list of types. Returns `Ok(None)` otherwise.
push( &mut self, offset: usize, module: &str, name: Option<&str>, ty: EntityType, types: &mut SnapshotList<TypeDef>, desc: &str, ) -> Result<Option<usize>>1854 fn push(
1855 &mut self,
1856 offset: usize,
1857 module: &str,
1858 name: Option<&str>,
1859 ty: EntityType,
1860 types: &mut SnapshotList<TypeDef>,
1861 desc: &str,
1862 ) -> Result<Option<usize>> {
1863 self.type_size = combine_type_sizes(offset, self.type_size, ty.size(types))?;
1864 let name = match name {
1865 Some(name) => name,
1866 // If the `name` is not provided then this is a module-linking style
1867 // definition with only one level of a name rather than two. This
1868 // means we can insert the `ty` into the set of imports directly,
1869 // error-ing out on duplicates.
1870 None => {
1871 let prev = self.set.insert(module.to_string(), ty);
1872 return if prev.is_some() {
1873 Err(BinaryReaderError::new(
1874 format!("duplicate {} name `{}` already defined", desc, module),
1875 offset,
1876 ))
1877 } else {
1878 Ok(None)
1879 };
1880 }
1881 };
1882 match self.set.get(module) {
1883 // If `module` was previously defined and we implicitly defined it,
1884 // then we know that it points to an instance type. We update the
1885 // set of exports of the instance type here since we're adding a new
1886 // entry. Note that nothing, at the point that we're building this
1887 // set, should point to this instance type so it should be safe to
1888 // mutate.
1889 Some(instance) if self.implicit.contains(module) => {
1890 let instance = match instance {
1891 EntityType::Instance(i) => match &mut types[*i] {
1892 TypeDef::Instance(i) => i,
1893 _ => unreachable!(),
1894 },
1895 _ => unreachable!(),
1896 };
1897 let prev = instance.exports.insert(name.to_string(), ty);
1898 if prev.is_some() {
1899 return Err(BinaryReaderError::new(
1900 format!(
1901 "duplicate {} name `{}::{}` already defined",
1902 desc, module, name
1903 ),
1904 offset,
1905 ));
1906 }
1907 Ok(None)
1908 }
1909
1910 // Otherwise `module` was previously defined, but it *wasn't*
1911 // implicitly defined through a two level import (rather was
1912 // explicitly defined with a single-level import), then that's an
1913 // error.
1914 Some(_) => {
1915 return Err(BinaryReaderError::new(
1916 format!("cannot define the {} `{}` twice", desc, module),
1917 offset,
1918 ))
1919 }
1920
1921 // And finally if `module` wasn't already defined then we go ahead
1922 // and define it here as a instance type with a single export, our
1923 // `name`.
1924 None => {
1925 let idx = types.len();
1926 let mut instance = InstanceType::default();
1927 instance.exports.insert(name.to_string(), ty);
1928 types.push(TypeDef::Instance(instance));
1929 assert!(self.implicit.insert(module.to_string()));
1930 self.set
1931 .insert(module.to_string(), EntityType::Instance(idx));
1932 Ok(Some(idx))
1933 }
1934 }
1935 }
1936 }
1937
1938 impl EntityType {
size(&self, list: &SnapshotList<TypeDef>) -> u321939 fn size(&self, list: &SnapshotList<TypeDef>) -> u32 {
1940 let recursive_size = match self {
1941 // Note that this function computes the size of the *type*, not the
1942 // size of the value, so these "leaves" all count as 1
1943 EntityType::Global(_) | EntityType::Memory(_) | EntityType::Table(_) => 1,
1944
1945 // These types have recursive sizes so we look up the size in the
1946 // type tables.
1947 EntityType::Func(i)
1948 | EntityType::Module(i)
1949 | EntityType::Instance(i)
1950 | EntityType::Event(i) => match &list[*i] {
1951 TypeDef::Func(f) => (f.params.len() + f.returns.len()) as u32,
1952 TypeDef::Module(m) => m.type_size,
1953 TypeDef::Instance(i) => i.type_size,
1954 },
1955 };
1956 recursive_size.saturating_add(1)
1957 }
1958 }
1959
1960 /// This is a type which mirrors a subset of the `Vec<T>` API, but is intended
1961 /// to be able to be cheaply snapshotted and cloned.
1962 ///
1963 /// When each module's code sections start we "commit" the current list of types
1964 /// in the global list of types. This means that the temporary `cur` vec here is
1965 /// pushed onto `snapshots` and wrapped up in an `Arc`. At that point we clone
1966 /// this entire list (which is then O(modules), not O(types in all modules)) and
1967 /// pass out as a context to each function validator.
1968 ///
1969 /// Otherwise, though, this type behaves as if it were a large `Vec<T>`, but
1970 /// it's represented by lists of contiguous chunks.
1971 struct SnapshotList<T> {
1972 // All previous snapshots, the "head" of the list that this type represents.
1973 // The first entry in this pair is the starting index for all elements
1974 // contained in the list, and the second element is the list itself. Note
1975 // the `Arc` wrapper around sub-lists, which makes cloning time for this
1976 // `SnapshotList` O(snapshots) rather than O(snapshots_total), which for
1977 // us in this context means the number of modules, not types.
1978 //
1979 // Note that this list is sorted least-to-greatest in order of the index for
1980 // binary searching.
1981 snapshots: Vec<(usize, Arc<Vec<T>>)>,
1982
1983 // This is the total length of all lists in the `snapshots` array.
1984 snapshots_total: usize,
1985
1986 // The current list of types for the current snapshot that are being built.
1987 cur: Vec<T>,
1988 }
1989
1990 impl<T> SnapshotList<T> {
1991 /// Same as `<&[T]>::get`
get(&self, index: usize) -> Option<&T>1992 fn get(&self, index: usize) -> Option<&T> {
1993 // Check to see if this index falls on our local list
1994 if index >= self.snapshots_total {
1995 return self.cur.get(index - self.snapshots_total);
1996 }
1997 // ... and failing that we do a binary search to figure out which bucket
1998 // it's in. Note the `i-1` in the `Err` case because if we don't find an
1999 // exact match the type is located in the previous bucket.
2000 let i = match self.snapshots.binary_search_by_key(&index, |(i, _)| *i) {
2001 Ok(i) => i,
2002 Err(i) => i - 1,
2003 };
2004 let (len, list) = &self.snapshots[i];
2005 Some(&list[index - len])
2006 }
2007
2008 /// Same as `<&mut [T]>::get_mut`, except only works for indexes into the
2009 /// current snapshot being built.
2010 ///
2011 /// # Panics
2012 ///
2013 /// Panics if an index is passed in which falls within the
2014 /// previously-snapshotted list of types. This should never happen in our
2015 /// contesxt and the panic is intended to weed out possible bugs in
2016 /// wasmparser.
get_mut(&mut self, index: usize) -> Option<&mut T>2017 fn get_mut(&mut self, index: usize) -> Option<&mut T> {
2018 if index >= self.snapshots_total {
2019 return self.cur.get_mut(index - self.snapshots_total);
2020 }
2021 panic!("cannot get a mutable reference in snapshotted part of list")
2022 }
2023
2024 /// Same as `Vec::push`
push(&mut self, val: T)2025 fn push(&mut self, val: T) {
2026 self.cur.push(val);
2027 }
2028
2029 /// Same as `<[T]>::len`
len(&self) -> usize2030 fn len(&self) -> usize {
2031 self.cur.len() + self.snapshots_total
2032 }
2033
2034 /// Commits previously pushed types into this snapshot vector, and returns a
2035 /// clone of this list.
2036 ///
2037 /// The returned `SnapshotList` can be used to access all the same types as
2038 /// this list itself. This list also is not changed (from an external
2039 /// perspective) and can continue to access all the same types.
commit(&mut self) -> SnapshotList<T>2040 fn commit(&mut self) -> SnapshotList<T> {
2041 // If the current chunk has new elements, commit them in to an
2042 // `Arc`-wrapped vector in the snapshots list. Note the `shrink_to_fit`
2043 // ahead of time to hopefully keep memory usage lower than it would
2044 // otherwise be.
2045 let len = self.cur.len();
2046 if len > 0 {
2047 self.cur.shrink_to_fit();
2048 self.snapshots
2049 .push((self.snapshots_total, Arc::new(mem::take(&mut self.cur))));
2050 self.snapshots_total += len;
2051 }
2052 SnapshotList {
2053 snapshots: self.snapshots.clone(),
2054 snapshots_total: self.snapshots_total,
2055 cur: Vec::new(),
2056 }
2057 }
2058 }
2059
2060 impl<T> std::ops::Index<usize> for SnapshotList<T> {
2061 type Output = T;
2062
index(&self, index: usize) -> &T2063 fn index(&self, index: usize) -> &T {
2064 self.get(index).unwrap()
2065 }
2066 }
2067
2068 impl<T> std::ops::IndexMut<usize> for SnapshotList<T> {
index_mut(&mut self, index: usize) -> &mut T2069 fn index_mut(&mut self, index: usize) -> &mut T {
2070 self.get_mut(index).unwrap()
2071 }
2072 }
2073
2074 impl<T> Default for SnapshotList<T> {
default() -> SnapshotList<T>2075 fn default() -> SnapshotList<T> {
2076 SnapshotList {
2077 snapshots: Vec::new(),
2078 snapshots_total: 0,
2079 cur: Vec::new(),
2080 }
2081 }
2082 }
2083