Coverage Report

Created: 2026-06-07 07:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wasmparser/src/validator.rs
Line
Count
Source
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::prelude::*;
17
use crate::{
18
    AbstractHeapType, BinaryReaderError, Encoding, FromReader, FunctionBody, HeapType, Parser,
19
    Payload, RefType, Result, SectionLimited, ValType, WASM_MODULE_VERSION, WasmFeatures,
20
    limits::*,
21
};
22
use ::core::mem;
23
use ::core::ops::Range;
24
use ::core::sync::atomic::{AtomicUsize, Ordering};
25
use alloc::sync::Arc;
26
27
/// Test whether the given buffer contains a valid WebAssembly module or component,
28
/// analogous to [`WebAssembly.validate`][js] in the JS API.
29
///
30
/// This functions requires the bytes to validate are entirely resident in memory.
31
/// Additionally this validates the given bytes with the default set of WebAssembly
32
/// features implemented by `wasmparser`.
33
///
34
/// For more fine-tuned control over validation it's recommended to review the
35
/// documentation of [`Validator`].
36
///
37
/// Upon success, the type information for the top-level module or component will
38
/// be returned.
39
///
40
/// [js]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/validate
41
7
pub fn validate(bytes: &[u8]) -> Result<Types> {
42
7
    Validator::new().validate_all(bytes)
43
7
}
44
45
#[test]
46
fn test_validate() {
47
    assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x1, 0x0, 0x0, 0x0]).is_ok());
48
    assert!(validate(&[0x0, 0x61, 0x73, 0x6d, 0x2, 0x0, 0x0, 0x0]).is_err());
49
}
50
51
#[cfg(feature = "component-model")]
52
mod component;
53
#[cfg(feature = "component-model")]
54
pub mod component_types;
55
mod core;
56
mod func;
57
#[cfg(feature = "component-model")]
58
pub mod names;
59
mod operators;
60
pub mod types;
61
62
#[cfg(feature = "component-model")]
63
use self::component::*;
64
pub use self::core::ValidatorResources;
65
use self::core::*;
66
use self::types::{TypeAlloc, Types, TypesRef};
67
pub use func::{FuncToValidate, FuncValidator, FuncValidatorAllocations};
68
pub use operators::Frame;
69
70
2.14M
fn check_max(cur_len: usize, amt_added: u32, max: usize, desc: &str, offset: usize) -> Result<()> {
71
2.14M
    if max
72
2.14M
        .checked_sub(cur_len)
73
2.14M
        .and_then(|amt| amt.checked_sub(amt_added as usize))
74
2.14M
        .is_none()
75
    {
76
0
        if max == 1 {
77
0
            bail!(offset, "multiple {desc}");
78
0
        }
79
80
0
        bail!(offset, "{desc} count exceeds limit of {max}");
81
2.14M
    }
82
83
2.14M
    Ok(())
84
2.14M
}
85
86
1.45M
fn combine_type_sizes(a: u32, b: u32, offset: usize) -> Result<u32> {
87
1.45M
    match a.checked_add(b) {
88
1.45M
        Some(sum) if sum < MAX_WASM_TYPE_SIZE => Ok(sum),
89
0
        _ => Err(format_err!(
90
0
            offset,
91
0
            "effective type size exceeds the limit of {MAX_WASM_TYPE_SIZE}",
92
0
        )),
93
    }
94
1.45M
}
95
96
/// A unique identifier for a particular `Validator`.
97
///
98
/// Allows you to save the `ValidatorId` of the [`Validator`][crate::Validator]
99
/// you get identifiers out of (e.g. [`CoreTypeId`][crate::types::CoreTypeId])
100
/// and then later assert that you are pairing those identifiers with the same
101
/// `Validator` instance when accessing the identifier's associated data.
102
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, PartialOrd, Ord)]
103
pub struct ValidatorId(usize);
104
105
impl Default for ValidatorId {
106
    #[inline]
107
39.1k
    fn default() -> Self {
108
        static ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
109
39.1k
        ValidatorId(ID_COUNTER.fetch_add(1, Ordering::AcqRel))
110
39.1k
    }
111
}
112
113
/// Validator for a WebAssembly binary module or component.
114
///
115
/// This structure encapsulates state necessary to validate a WebAssembly
116
/// binary. This implements validation as defined by the [core
117
/// specification][core]. A `Validator` is designed, like
118
/// [`Parser`], to accept incremental input over time.
119
/// Additionally a `Validator` is also designed for parallel validation of
120
/// functions as they are received.
121
///
122
/// It's expected that you'll be using a [`Parser`] in tandem with a
123
/// `Validator`. As each [`Payload`](crate::Payload) is received from a
124
/// [`Parser`] you'll pass it into a `Validator` to test the validity of the
125
/// payload. Note that all payloads received from a [`Parser`] are expected to
126
/// be passed to a [`Validator`]. For example if you receive
127
/// [`Payload::TypeSection`](crate::Payload) you'll call
128
/// [`Validator::type_section`] to validate this.
129
///
130
/// The design of [`Validator`] is intended that you'll interleave, in your own
131
/// application's processing, calls to validation. Each variant, after it's
132
/// received, will be validated and then your application would proceed as
133
/// usual. At all times, however, you'll have access to the [`Validator`] and
134
/// the validation context up to that point. This enables applications to check
135
/// the types of functions and learn how many globals there are, for example.
136
///
137
/// [core]: https://webassembly.github.io/spec/core/valid/index.html
138
#[derive(Default)]
139
pub struct Validator {
140
    id: ValidatorId,
141
142
    /// The current state of the validator.
143
    state: State,
144
145
    /// The global type space used by the validator and any sub-validators.
146
    types: TypeAlloc,
147
148
    /// The module state when parsing a WebAssembly module.
149
    module: Option<ModuleState>,
150
151
    /// With the component model enabled, this stores the pushed component states.
152
    /// The top of the stack is the current component state.
153
    #[cfg(feature = "component-model")]
154
    components: Vec<ComponentState>,
155
156
    /// Enabled WebAssembly feature flags, dictating what's valid and what
157
    /// isn't.
158
    features: WasmFeatures,
159
}
160
161
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
162
enum State {
163
    /// A header has not yet been parsed.
164
    ///
165
    /// The value is the expected encoding for the header.
166
    Unparsed(Option<Encoding>),
167
    /// A module header has been parsed.
168
    ///
169
    /// The associated module state is available via [`Validator::module`].
170
    Module,
171
    /// A component header has been parsed.
172
    ///
173
    /// The associated component state exists at the top of the
174
    /// validator's [`Validator::components`] stack.
175
    #[cfg(feature = "component-model")]
176
    Component,
177
    /// The parse has completed and no more data is expected.
178
    End,
179
}
180
181
impl State {
182
886k
    fn ensure_parsable(&self, offset: usize) -> Result<()> {
183
886k
        match self {
184
480k
            Self::Module => Ok(()),
185
            #[cfg(feature = "component-model")]
186
406k
            Self::Component => Ok(()),
187
0
            Self::Unparsed(_) => Err(BinaryReaderError::new(
188
0
                "unexpected section before header was parsed",
189
0
                offset,
190
0
            )),
191
0
            Self::End => Err(BinaryReaderError::new(
192
0
                "unexpected section after parsing has completed",
193
0
                offset,
194
0
            )),
195
        }
196
886k
    }
197
198
480k
    fn ensure_module(&self, section: &str, offset: usize) -> Result<()> {
199
480k
        self.ensure_parsable(offset)?;
200
480k
        let _ = section;
201
202
480k
        match self {
203
480k
            Self::Module => Ok(()),
204
            #[cfg(feature = "component-model")]
205
0
            Self::Component => Err(format_err!(
206
0
                offset,
207
0
                "unexpected module {section} section while parsing a component",
208
0
            )),
209
0
            _ => unreachable!(),
210
        }
211
480k
    }
212
213
    #[cfg(feature = "component-model")]
214
406k
    fn ensure_component(&self, section: &str, offset: usize) -> Result<()> {
215
406k
        self.ensure_parsable(offset)?;
216
217
406k
        match self {
218
406k
            Self::Component => Ok(()),
219
0
            Self::Module => Err(format_err!(
220
0
                offset,
221
0
                "unexpected component {section} section while parsing a module",
222
0
            )),
223
0
            _ => unreachable!(),
224
        }
225
406k
    }
226
}
227
228
impl Default for State {
229
39.1k
    fn default() -> Self {
230
39.1k
        Self::Unparsed(None)
231
39.1k
    }
232
}
233
234
impl WasmFeatures {
235
    /// NOTE: This only checks that the value type corresponds to the feature set!!
236
    ///
237
    /// To check that reference types are valid, we need access to the module
238
    /// types. Use module.check_value_type.
239
4.29M
    pub(crate) fn check_value_type(&self, ty: ValType) -> Result<(), &'static str> {
240
4.29M
        match ty {
241
2.52M
            ValType::I32 | ValType::I64 => Ok(()),
242
            ValType::F32 | ValType::F64 => {
243
1.24M
                if self.floats() {
244
1.24M
                    Ok(())
245
                } else {
246
0
                    Err("floating-point support is disabled")
247
                }
248
            }
249
442k
            ValType::Ref(r) => self.check_ref_type(r),
250
            ValType::V128 => {
251
89.0k
                if self.simd() {
252
89.0k
                    Ok(())
253
                } else {
254
0
                    Err("SIMD support is not enabled")
255
                }
256
            }
257
        }
258
4.29M
    }
259
260
1.02M
    pub(crate) fn check_ref_type(&self, r: RefType) -> Result<(), &'static str> {
261
1.02M
        if !self.reference_types() {
262
0
            return Err("reference types support is not enabled");
263
1.02M
        }
264
1.02M
        match r.heap_type() {
265
            HeapType::Concrete(_) => {
266
                // Note that `self.gc_types()` is not checked here because
267
                // concrete pointers to function types are allowed. GC types
268
                // are disallowed by instead rejecting the definition of
269
                // array/struct types and only allowing the definition of
270
                // function types.
271
272
                // Indexed types require either the function-references or gc
273
                // proposal as gc implies function references here.
274
164k
                if self.function_references() || self.gc() {
275
164k
                    Ok(())
276
                } else {
277
0
                    Err("function references required for index reference types")
278
                }
279
            }
280
            HeapType::Exact(_) => {
281
                // Exact types were introduced with the custom descriptors
282
                // proposal.
283
0
                if self.custom_descriptors() {
284
0
                    Ok(())
285
                } else {
286
0
                    Err("custom descriptors required for exact reference types")
287
                }
288
            }
289
855k
            HeapType::Abstract { shared, ty } => {
290
                use AbstractHeapType::*;
291
855k
                if shared && !self.shared_everything_threads() {
292
0
                    return Err(
293
0
                        "shared reference types require the shared-everything-threads proposal",
294
0
                    );
295
855k
                }
296
297
                // Apply the "gc-types" feature which disallows all heap types
298
                // except exnref/funcref.
299
855k
                if !self.gc_types() && ty != Func && ty != Exn {
300
0
                    return Err("gc types are disallowed but found type which requires gc");
301
855k
                }
302
303
855k
                match (ty, r.is_nullable()) {
304
                    // funcref/externref only require `reference-types`.
305
623k
                    (Func, true) | (Extern, true) => Ok(()),
306
307
                    // Non-nullable func/extern references requires the
308
                    // `function-references` proposal.
309
                    (Func | Extern, false) => {
310
0
                        if self.function_references() {
311
0
                            Ok(())
312
                        } else {
313
0
                            Err("function references required for non-nullable types")
314
                        }
315
                    }
316
317
                    // These types were added in the gc proposal.
318
                    (Any | None | Eq | Struct | Array | I31 | NoExtern | NoFunc, _) => {
319
196k
                        if self.gc() {
320
196k
                            Ok(())
321
                        } else {
322
0
                            Err("heap types not supported without the gc feature")
323
                        }
324
                    }
325
326
                    // These types were added in the exception-handling proposal.
327
                    (Exn | NoExn, _) => {
328
35.8k
                        if self.exceptions() {
329
35.8k
                            Ok(())
330
                        } else {
331
0
                            Err(
332
0
                                "exception refs not supported without the exception handling feature",
333
0
                            )
334
                        }
335
                    }
336
337
                    // These types were added in the stack switching proposal.
338
                    (Cont | NoCont, _) => {
339
0
                        if self.stack_switching() {
340
0
                            Ok(())
341
                        } else {
342
0
                            Err(
343
0
                                "continuation refs not supported without the stack switching feature",
344
0
                            )
345
                        }
346
                    }
347
                }
348
            }
349
        }
350
1.02M
    }
351
}
352
353
/// Possible return values from [`Validator::payload`].
354
#[allow(clippy::large_enum_variant)]
355
pub enum ValidPayload<'a> {
356
    /// The payload validated, no further action need be taken.
357
    Ok,
358
    /// The payload validated, but it started a nested module or component.
359
    ///
360
    /// This result indicates that the specified parser should be used instead
361
    /// of the currently-used parser until this returned one ends.
362
    Parser(Parser),
363
    /// A function was found to be validated.
364
    Func(FuncToValidate<ValidatorResources>, FunctionBody<'a>),
365
    /// The end payload was validated and the types known to the validator
366
    /// are provided.
367
    End(Types),
368
}
369
370
impl Validator {
371
    /// Creates a new [`Validator`] ready to validate a WebAssembly module
372
    /// or component.
373
    ///
374
    /// The new validator will receive payloads parsed from
375
    /// [`Parser`], and expects the first payload received to be
376
    /// the version header from the parser.
377
39.1k
    pub fn new() -> Validator {
378
39.1k
        Validator::default()
379
39.1k
    }
380
381
    /// Creates a new [`Validator`] which has the specified set of wasm
382
    /// features activated for validation.
383
    ///
384
    /// This function is the same as [`Validator::new`] except it also allows
385
    /// you to customize the active wasm features in use for validation. This
386
    /// can allow enabling experimental proposals or also turning off
387
    /// on-by-default wasm proposals.
388
39.1k
    pub fn new_with_features(features: WasmFeatures) -> Validator {
389
39.1k
        let mut ret = Validator::new();
390
39.1k
        ret.features = features;
391
39.1k
        ret
392
39.1k
    }
393
394
    /// Returns the wasm features used for this validator.
395
0
    pub fn features(&self) -> &WasmFeatures {
396
0
        &self.features
397
0
    }
398
399
    /// Reset this validator's state such that it is ready to validate a new
400
    /// Wasm module or component.
401
    ///
402
    /// This does *not* clear or reset the internal state keeping track of
403
    /// validated (and deduplicated and canonicalized) types, allowing you to
404
    /// use the same type identifiers (such as
405
    /// [`CoreTypeId`][crate::types::CoreTypeId]) for the same types that are
406
    /// defined multiple times across different modules and components.
407
    ///
408
    /// # Panics
409
    ///
410
    /// This function will panic if the validator was mid-way through
411
    /// validating a binary. Validation must complete entirely or not have
412
    /// started at all for this method to be called.
413
    ///
414
    /// # Examples
415
    ///
416
    /// ```
417
    /// fn foo() -> anyhow::Result<()> {
418
    /// use wasmparser::Validator;
419
    ///
420
    /// let mut validator = Validator::default();
421
    ///
422
    /// // Two wasm modules, both of which define the same type, but at
423
    /// // different indices in their respective types index spaces.
424
    /// let wasm1 = wat::parse_str("
425
    ///     (module
426
    ///         (type $same_type (func (param i32) (result f64)))
427
    ///     )
428
    /// ")?;
429
    /// let wasm2 = wat::parse_str("
430
    ///     (module
431
    ///         (type $different_type (func))
432
    ///         (type $same_type (func (param i32) (result f64)))
433
    ///     )
434
    /// ")?;
435
    ///
436
    /// // Validate the first Wasm module and get the ID of its type.
437
    /// let types = validator.validate_all(&wasm1)?;
438
    /// let id1 = types.as_ref().core_type_at_in_module(0);
439
    ///
440
    /// // Reset the validator so we can parse the second wasm module inside
441
    /// // this validator's same context.
442
    /// validator.reset();
443
    ///
444
    /// // Validate the second Wasm module and get the ID of its second type,
445
    /// // which is the same type as the first Wasm module's only type.
446
    /// let types = validator.validate_all(&wasm2)?;
447
    /// let id2 = types.as_ref().core_type_at_in_module(1);
448
    ///
449
    /// // Because both modules were processed in the same `Validator`, they
450
    /// // share the same types context and therefore the same type defined
451
    /// // multiple times across different modules will be deduplicated and
452
    /// // assigned the same identifier!
453
    /// assert_eq!(id1, id2);
454
    /// assert_eq!(types[id1], types[id2]);
455
    /// # Ok(())
456
    /// # }
457
    /// # foo().unwrap()
458
    /// ```
459
0
    pub fn reset(&mut self) {
460
        let Validator {
461
            // Not changing the identifier; users should be able to observe that
462
            // they are using the same validation context, even after resetting.
463
            id: _,
464
465
            // Don't mess with `types`, we specifically want to reuse canonicalization.
466
            types: _,
467
468
            // Also leave features as they are. While this is perhaps not
469
            // strictly necessary, it helps us avoid weird bugs where we have
470
            // different views of what is or is not a valid type at different
471
            // times, despite using the same `TypeList` and hash consing
472
            // context, and therefore there could be moments in time where we
473
            // have "invalid" types inside our current types list.
474
            features: _,
475
476
0
            state,
477
0
            module,
478
            #[cfg(feature = "component-model")]
479
0
            components,
480
0
        } = self;
481
482
0
        assert!(
483
0
            matches!(state, State::End) || matches!(state, State::Unparsed(None)),
484
            "cannot reset a validator that did not successfully complete validation"
485
        );
486
0
        assert!(module.is_none());
487
        #[cfg(feature = "component-model")]
488
0
        assert!(components.is_empty());
489
490
0
        *state = State::default();
491
0
    }
492
493
    /// Get this validator's unique identifier.
494
    ///
495
    /// Allows you to assert that you are always working with the same
496
    /// `Validator` instance, when you can't otherwise statically ensure that
497
    /// property by e.g. storing a reference to the validator inside your
498
    /// structure.
499
0
    pub fn id(&self) -> ValidatorId {
500
0
        self.id
501
0
    }
502
503
    /// Validates an entire in-memory module or component with this validator.
504
    ///
505
    /// This function will internally create a [`Parser`] to parse the `bytes`
506
    /// provided. The entire module or component specified by `bytes` will be
507
    /// parsed and validated.
508
    ///
509
    /// Upon success, the type information for the top-level module or component
510
    /// will be returned.
511
19.3k
    pub fn validate_all(&mut self, bytes: &[u8]) -> Result<Types> {
512
19.3k
        let mut functions_to_validate = Vec::new();
513
19.3k
        let mut last_types = None;
514
19.3k
        let mut parser = Parser::new(0);
515
19.3k
        let _ = &mut parser;
516
        #[cfg(feature = "features")]
517
19.3k
        parser.set_features(self.features);
518
552k
        for payload in parser.parse_all(bytes) {
519
552k
            match self.payload(&payload?)? {
520
226k
                ValidPayload::Func(a, b) => {
521
226k
                    functions_to_validate.push((a, b));
522
226k
                }
523
29.8k
                ValidPayload::End(types) => {
524
29.8k
                    // Only the last (top-level) type information will be returned
525
29.8k
                    last_types = Some(types);
526
29.8k
                }
527
296k
                _ => {}
528
            }
529
        }
530
531
19.3k
        let mut allocs = FuncValidatorAllocations::default();
532
226k
        for (func, body) in functions_to_validate {
533
226k
            let mut validator = func.into_validator(allocs);
534
226k
            validator.validate(&body)?;
535
226k
            allocs = validator.into_allocations();
536
        }
537
538
19.3k
        Ok(last_types.unwrap())
539
19.3k
    }
540
541
    /// Gets the types known by the validator so far within the
542
    /// module/component `level` modules/components up from the
543
    /// module/component currently being parsed.
544
    ///
545
    /// For instance, calling `validator.types(0)` will get the types of the
546
    /// module/component currently being parsed, and `validator.types(1)` will
547
    /// get the types of the component containing that module/component.
548
    ///
549
    /// Returns `None` if there is no module/component that many levels up.
550
42.0k
    pub fn types(&self, mut level: usize) -> Option<TypesRef<'_>> {
551
42.0k
        if let Some(module) = &self.module {
552
42.0k
            if level == 0 {
553
42.0k
                return Some(TypesRef::from_module(self.id, &self.types, &module.module));
554
0
            } else {
555
0
                level -= 1;
556
0
                let _ = level;
557
0
            }
558
0
        }
559
560
        #[cfg(feature = "component-model")]
561
0
        return self
562
0
            .components
563
0
            .iter()
564
0
            .nth_back(level)
565
0
            .map(|component| TypesRef::from_component(self.id, &self.types, component));
566
        #[cfg(not(feature = "component-model"))]
567
        return None;
568
42.0k
    }
569
570
    /// Convenience function to validate a single [`Payload`].
571
    ///
572
    /// This function is intended to be used as a convenience. It will
573
    /// internally perform any validation necessary to validate the [`Payload`]
574
    /// provided. The convenience part is that you're likely already going to
575
    /// be matching on [`Payload`] in your application, at which point it's more
576
    /// appropriate to call the individual methods on [`Validator`] per-variant
577
    /// in [`Payload`], such as [`Validator::type_section`].
578
    ///
579
    /// This function returns a [`ValidPayload`] variant on success, indicating
580
    /// one of a few possible actions that need to be taken after a payload is
581
    /// validated. For example function contents are not validated here, they're
582
    /// returned through [`ValidPayload`] for validation by the caller.
583
1.09M
    pub fn payload<'a>(&mut self, payload: &Payload<'a>) -> Result<ValidPayload<'a>> {
584
        use crate::Payload::*;
585
1.09M
        match payload {
586
            Version {
587
70.7k
                num,
588
70.7k
                encoding,
589
70.7k
                range,
590
70.7k
            } => self.version(*num, *encoding, range)?,
591
592
            // Module sections
593
40.1k
            TypeSection(s) => self.type_section(s)?,
594
25.2k
            ImportSection(s) => self.import_section(s)?,
595
25.6k
            FunctionSection(s) => self.function_section(s)?,
596
7.46k
            TableSection(s) => self.table_section(s)?,
597
19.5k
            MemorySection(s) => self.memory_section(s)?,
598
548
            TagSection(s) => self.tag_section(s)?,
599
8.94k
            GlobalSection(s) => self.global_section(s)?,
600
21.1k
            ExportSection(s) => self.export_section(s)?,
601
11.1k
            StartSection { func, range } => self.start_section(*func, range)?,
602
6.01k
            ElementSection(s) => self.element_section(s)?,
603
2.06k
            DataCountSection { count, range } => self.data_count_section(*count, range)?,
604
            CodeSectionStart {
605
                count: _,
606
25.6k
                range,
607
                size: _,
608
25.6k
            } => self.code_section_start(range)?,
609
283k
            CodeSectionEntry(body) => {
610
283k
                let func_validator = self.code_section_entry(body)?;
611
283k
                return Ok(ValidPayload::Func(func_validator, body.clone()));
612
            }
613
3.10k
            DataSection(s) => self.data_section(s)?,
614
615
            // Component sections
616
            #[cfg(feature = "component-model")]
617
            ModuleSection {
618
25.4k
                parser,
619
25.4k
                unchecked_range: range,
620
                ..
621
            } => {
622
25.4k
                self.module_section(range)?;
623
25.4k
                return Ok(ValidPayload::Parser(parser.clone()));
624
            }
625
            #[cfg(feature = "component-model")]
626
29.2k
            InstanceSection(s) => self.instance_section(s)?,
627
            #[cfg(feature = "component-model")]
628
0
            CoreTypeSection(s) => self.core_type_section(s)?,
629
            #[cfg(feature = "component-model")]
630
            ComponentSection {
631
6.14k
                parser,
632
6.14k
                unchecked_range: range,
633
                ..
634
            } => {
635
6.14k
                self.component_section(range)?;
636
6.14k
                return Ok(ValidPayload::Parser(parser.clone()));
637
            }
638
            #[cfg(feature = "component-model")]
639
6.14k
            ComponentInstanceSection(s) => self.component_instance_section(s)?,
640
            #[cfg(feature = "component-model")]
641
34.8k
            ComponentAliasSection(s) => self.component_alias_section(s)?,
642
            #[cfg(feature = "component-model")]
643
137k
            ComponentTypeSection(s) => self.component_type_section(s)?,
644
            #[cfg(feature = "component-model")]
645
28.2k
            ComponentCanonicalSection(s) => self.component_canonical_section(s)?,
646
            #[cfg(feature = "component-model")]
647
0
            ComponentStartSection { start, range } => self.component_start_section(start, range)?,
648
            #[cfg(feature = "component-model")]
649
19.6k
            ComponentImportSection(s) => self.component_import_section(s)?,
650
            #[cfg(feature = "component-model")]
651
118k
            ComponentExportSection(s) => self.component_export_section(s)?,
652
653
70.7k
            End(offset) => return Ok(ValidPayload::End(self.end(*offset)?)),
654
655
65.3k
            CustomSection { .. } => {} // no validation for custom sections
656
0
            UnknownSection { id, range, .. } => self.unknown_section(*id, range)?,
657
        }
658
707k
        Ok(ValidPayload::Ok)
659
1.09M
    }
660
661
    /// Validates [`Payload::Version`](crate::Payload).
662
70.7k
    pub fn version(&mut self, num: u16, encoding: Encoding, range: &Range<usize>) -> Result<()> {
663
70.7k
        match &self.state {
664
70.7k
            State::Unparsed(expected) => {
665
70.7k
                if let Some(expected) = expected {
666
31.6k
                    if *expected != encoding {
667
0
                        bail!(
668
0
                            range.start,
669
                            "expected a version header for a {}",
670
0
                            match expected {
671
0
                                Encoding::Module => "module",
672
0
                                Encoding::Component => "component",
673
                            }
674
                        );
675
31.6k
                    }
676
39.1k
                }
677
            }
678
            _ => {
679
0
                return Err(BinaryReaderError::new(
680
0
                    "wasm version header out of order",
681
0
                    range.start,
682
0
                ));
683
            }
684
        }
685
686
70.7k
        self.state = match encoding {
687
            Encoding::Module => {
688
41.4k
                if num == WASM_MODULE_VERSION {
689
41.4k
                    assert!(self.module.is_none());
690
41.4k
                    self.module = Some(ModuleState::new(self.features));
691
41.4k
                    State::Module
692
                } else {
693
0
                    bail!(range.start, "unknown binary version: {num:#x}");
694
                }
695
            }
696
            Encoding::Component => {
697
29.3k
                if !self.features.component_model() {
698
0
                    bail!(
699
0
                        range.start,
700
                        "unknown binary version and encoding combination: {num:#x} and 0x1, \
701
                        note: encoded as a component but the WebAssembly component model feature \
702
                        is not enabled - enable the feature to allow component validation",
703
                    );
704
29.3k
                }
705
                #[cfg(feature = "component-model")]
706
29.3k
                if num == crate::WASM_COMPONENT_VERSION {
707
29.3k
                    self.components
708
29.3k
                        .push(ComponentState::new(ComponentKind::Component, self.features));
709
29.3k
                    State::Component
710
0
                } else if num < crate::WASM_COMPONENT_VERSION {
711
0
                    bail!(range.start, "unsupported component version: {num:#x}");
712
                } else {
713
0
                    bail!(range.start, "unknown component version: {num:#x}");
714
                }
715
                #[cfg(not(feature = "component-model"))]
716
                bail!(
717
                    range.start,
718
                    "component model validation support disabled \
719
                     at compile time"
720
                );
721
            }
722
        };
723
724
70.7k
        Ok(())
725
70.7k
    }
726
727
    /// Validates [`Payload::TypeSection`](crate::Payload).
728
40.1k
    pub fn type_section(&mut self, section: &crate::TypeSectionReader<'_>) -> Result<()> {
729
40.1k
        self.process_module_section(
730
40.1k
            section,
731
40.1k
            "type",
732
40.1k
            |state, _types, count, offset| {
733
40.1k
                check_max(
734
40.1k
                    state.module.types.len(),
735
40.1k
                    count,
736
                    MAX_WASM_TYPES,
737
40.1k
                    "types",
738
40.1k
                    offset,
739
0
                )?;
740
40.1k
                state.module.assert_mut().types.reserve(count as usize);
741
40.1k
                Ok(())
742
40.1k
            },
743
146k
            |state, types, rec_group, offset| {
744
146k
                state
745
146k
                    .module
746
146k
                    .assert_mut()
747
146k
                    .add_types(rec_group, types, offset, true)?;
748
146k
                Ok(())
749
146k
            },
750
        )
751
40.1k
    }
752
753
    /// Validates [`Payload::ImportSection`](crate::Payload).
754
    ///
755
    /// This method should only be called when parsing a module.
756
25.2k
    pub fn import_section(&mut self, section: &crate::ImportSectionReader<'_>) -> Result<()> {
757
25.2k
        self.process_module_section(
758
25.2k
            section,
759
25.2k
            "import",
760
25.2k
            |state, _, count, offset| {
761
25.2k
                check_max(
762
25.2k
                    state.module.imports.len(),
763
25.2k
                    count,
764
                    MAX_WASM_IMPORTS,
765
25.2k
                    "imports",
766
25.2k
                    offset,
767
0
                )?;
768
25.2k
                state.module.assert_mut().imports.reserve(count as usize);
769
25.2k
                Ok(())
770
25.2k
            },
771
145k
            |state, types, imports, _offset| {
772
145k
                let state = state.module.assert_mut();
773
145k
                for import_and_offset in imports {
774
145k
                    let (offset, import) = import_and_offset?;
775
145k
                    state.add_import(import, types, offset)?;
776
                }
777
145k
                Ok(())
778
145k
            },
779
        )
780
25.2k
    }
781
782
    /// Validates [`Payload::FunctionSection`](crate::Payload).
783
    ///
784
    /// This method should only be called when parsing a module.
785
25.6k
    pub fn function_section(&mut self, section: &crate::FunctionSectionReader<'_>) -> Result<()> {
786
25.6k
        self.process_module_section(
787
25.6k
            section,
788
25.6k
            "function",
789
25.6k
            |state, _, count, offset| {
790
25.6k
                check_max(
791
25.6k
                    state.module.functions.len(),
792
25.6k
                    count,
793
                    MAX_WASM_FUNCTIONS,
794
25.6k
                    "functions",
795
25.6k
                    offset,
796
0
                )?;
797
25.6k
                state.module.assert_mut().functions.reserve(count as usize);
798
25.6k
                Ok(())
799
25.6k
            },
800
283k
            |state, types, ty, offset| state.module.assert_mut().add_function(ty, types, offset),
801
        )
802
25.6k
    }
803
804
    /// Validates [`Payload::TableSection`](crate::Payload).
805
    ///
806
    /// This method should only be called when parsing a module.
807
7.46k
    pub fn table_section(&mut self, section: &crate::TableSectionReader<'_>) -> Result<()> {
808
7.46k
        self.process_module_section(
809
7.46k
            section,
810
7.46k
            "table",
811
7.46k
            |state, _, count, offset| {
812
7.46k
                check_max(
813
7.46k
                    state.module.tables.len(),
814
7.46k
                    count,
815
7.46k
                    state.module.max_tables(),
816
7.46k
                    "tables",
817
7.46k
                    offset,
818
0
                )?;
819
7.46k
                state.module.assert_mut().tables.reserve(count as usize);
820
7.46k
                Ok(())
821
7.46k
            },
822
21.2k
            |state, types, table, offset| state.add_table(table, types, offset),
823
        )
824
7.46k
    }
825
826
    /// Validates [`Payload::MemorySection`](crate::Payload).
827
    ///
828
    /// This method should only be called when parsing a module.
829
19.5k
    pub fn memory_section(&mut self, section: &crate::MemorySectionReader<'_>) -> Result<()> {
830
19.5k
        self.process_module_section(
831
19.5k
            section,
832
19.5k
            "memory",
833
19.5k
            |state, _, count, offset| {
834
19.5k
                check_max(
835
19.5k
                    state.module.memories.len(),
836
19.5k
                    count,
837
19.5k
                    state.module.max_memories(),
838
19.5k
                    "memories",
839
19.5k
                    offset,
840
0
                )?;
841
19.5k
                state.module.assert_mut().memories.reserve(count as usize);
842
19.5k
                Ok(())
843
19.5k
            },
844
47.5k
            |state, _, ty, offset| state.module.assert_mut().add_memory(ty, offset),
845
        )
846
19.5k
    }
847
848
    /// Validates [`Payload::TagSection`](crate::Payload).
849
    ///
850
    /// This method should only be called when parsing a module.
851
548
    pub fn tag_section(&mut self, section: &crate::TagSectionReader<'_>) -> Result<()> {
852
548
        if !self.features.exceptions() {
853
0
            return Err(BinaryReaderError::new(
854
0
                "exceptions proposal not enabled",
855
0
                section.range().start,
856
0
            ));
857
548
        }
858
548
        self.process_module_section(
859
548
            section,
860
548
            "tag",
861
548
            |state, _, count, offset| {
862
548
                check_max(
863
548
                    state.module.tags.len(),
864
548
                    count,
865
                    MAX_WASM_TAGS,
866
548
                    "tags",
867
548
                    offset,
868
0
                )?;
869
548
                state.module.assert_mut().tags.reserve(count as usize);
870
548
                Ok(())
871
548
            },
872
8.79k
            |state, types, ty, offset| state.module.assert_mut().add_tag(ty, types, offset),
873
        )
874
548
    }
875
876
    /// Validates [`Payload::GlobalSection`](crate::Payload).
877
    ///
878
    /// This method should only be called when parsing a module.
879
8.94k
    pub fn global_section(&mut self, section: &crate::GlobalSectionReader<'_>) -> Result<()> {
880
8.94k
        self.process_module_section(
881
8.94k
            section,
882
8.94k
            "global",
883
8.94k
            |state, _, count, offset| {
884
8.94k
                check_max(
885
8.94k
                    state.module.globals.len(),
886
8.94k
                    count,
887
                    MAX_WASM_GLOBALS,
888
8.94k
                    "globals",
889
8.94k
                    offset,
890
0
                )?;
891
8.94k
                state.module.assert_mut().globals.reserve(count as usize);
892
8.94k
                Ok(())
893
8.94k
            },
894
108k
            |state, types, global, offset| state.add_global(global, types, offset),
895
        )
896
8.94k
    }
897
898
    /// Validates [`Payload::ExportSection`](crate::Payload).
899
    ///
900
    /// This method should only be called when parsing a module.
901
21.1k
    pub fn export_section(&mut self, section: &crate::ExportSectionReader<'_>) -> Result<()> {
902
21.1k
        self.process_module_section(
903
21.1k
            section,
904
21.1k
            "export",
905
21.1k
            |state, _, count, offset| {
906
21.1k
                check_max(
907
21.1k
                    state.module.exports.len(),
908
21.1k
                    count,
909
                    MAX_WASM_EXPORTS,
910
21.1k
                    "exports",
911
21.1k
                    offset,
912
0
                )?;
913
21.1k
                state.module.assert_mut().exports.reserve(count as usize);
914
21.1k
                Ok(())
915
21.1k
            },
916
135k
            |state, types, e, offset| {
917
135k
                let state = state.module.assert_mut();
918
135k
                let ty = state.export_to_entity_type(&e, offset)?;
919
135k
                state.add_export(e.name, ty, offset, false /* checked above */, types)
920
135k
            },
921
        )
922
21.1k
    }
923
924
    /// Validates [`Payload::StartSection`](crate::Payload).
925
    ///
926
    /// This method should only be called when parsing a module.
927
11.1k
    pub fn start_section(&mut self, func: u32, range: &Range<usize>) -> Result<()> {
928
11.1k
        let offset = range.start;
929
11.1k
        self.state.ensure_module("start", offset)?;
930
11.1k
        let state = self.module.as_mut().unwrap();
931
932
11.1k
        let ty = state.module.get_func_type(func, &self.types, offset)?;
933
11.1k
        if !ty.params().is_empty() || !ty.results().is_empty() {
934
0
            return Err(BinaryReaderError::new(
935
0
                "invalid start function type",
936
0
                offset,
937
0
            ));
938
11.1k
        }
939
940
11.1k
        Ok(())
941
11.1k
    }
942
943
    /// Validates [`Payload::ElementSection`](crate::Payload).
944
    ///
945
    /// This method should only be called when parsing a module.
946
6.01k
    pub fn element_section(&mut self, section: &crate::ElementSectionReader<'_>) -> Result<()> {
947
6.01k
        self.process_module_section(
948
6.01k
            section,
949
6.01k
            "element",
950
6.01k
            |state, _, count, offset| {
951
6.01k
                check_max(
952
6.01k
                    state.module.element_types.len(),
953
6.01k
                    count,
954
                    MAX_WASM_ELEMENT_SEGMENTS,
955
6.01k
                    "element segments",
956
6.01k
                    offset,
957
0
                )?;
958
6.01k
                state
959
6.01k
                    .module
960
6.01k
                    .assert_mut()
961
6.01k
                    .element_types
962
6.01k
                    .reserve(count as usize);
963
6.01k
                Ok(())
964
6.01k
            },
965
34.8k
            |state, types, e, offset| state.add_element_segment(e, types, offset),
966
        )
967
6.01k
    }
968
969
    /// Validates [`Payload::DataCountSection`](crate::Payload).
970
    ///
971
    /// This method should only be called when parsing a module.
972
2.06k
    pub fn data_count_section(&mut self, count: u32, range: &Range<usize>) -> Result<()> {
973
2.06k
        let offset = range.start;
974
2.06k
        self.state.ensure_module("data count", offset)?;
975
976
2.06k
        let state = self.module.as_mut().unwrap();
977
978
2.06k
        if count > MAX_WASM_DATA_SEGMENTS as u32 {
979
0
            return Err(BinaryReaderError::new(
980
0
                "data count section specifies too many data segments",
981
0
                offset,
982
0
            ));
983
2.06k
        }
984
985
2.06k
        state.module.assert_mut().data_count = Some(count);
986
2.06k
        Ok(())
987
2.06k
    }
988
989
    /// Validates [`Payload::CodeSectionStart`](crate::Payload).
990
    ///
991
    /// This method should only be called when parsing a module.
992
25.6k
    pub fn code_section_start(&mut self, range: &Range<usize>) -> Result<()> {
993
25.6k
        let offset = range.start;
994
25.6k
        self.state.ensure_module("code", offset)?;
995
996
25.6k
        let state = self.module.as_mut().unwrap();
997
998
        // Take a snapshot of the types when we start the code section.
999
25.6k
        state.module.assert_mut().snapshot = Some(Arc::new(self.types.commit()));
1000
1001
25.6k
        Ok(())
1002
25.6k
    }
1003
1004
    /// Validates [`Payload::CodeSectionEntry`](crate::Payload).
1005
    ///
1006
    /// This function will prepare a [`FuncToValidate`] which can be used to
1007
    /// create a [`FuncValidator`] to validate the function. The function body
1008
    /// provided will not be parsed or validated by this function.
1009
    ///
1010
    /// Note that the returned [`FuncToValidate`] is "connected" to this
1011
    /// [`Validator`] in that it uses the internal context of this validator for
1012
    /// validating the function. The [`FuncToValidate`] can be sent to another
1013
    /// thread, for example, to offload actual processing of functions
1014
    /// elsewhere.
1015
    ///
1016
    /// This method should only be called when parsing a module.
1017
283k
    pub fn code_section_entry(
1018
283k
        &mut self,
1019
283k
        body: &crate::FunctionBody,
1020
283k
    ) -> Result<FuncToValidate<ValidatorResources>> {
1021
283k
        let offset = body.range().start;
1022
283k
        self.state.ensure_module("code", offset)?;
1023
283k
        check_max(
1024
            0,
1025
283k
            u32::try_from(body.range().len())
1026
283k
                .expect("usize already validated to u32 during section-length decoding"),
1027
            MAX_WASM_FUNCTION_SIZE,
1028
283k
            "function body size",
1029
283k
            offset,
1030
0
        )?;
1031
1032
283k
        let state = self.module.as_mut().unwrap();
1033
1034
283k
        let (index, ty) = state.next_code_index_and_type();
1035
283k
        Ok(FuncToValidate {
1036
283k
            index,
1037
283k
            ty,
1038
283k
            resources: ValidatorResources(state.module.arc().clone()),
1039
283k
            features: self.features,
1040
283k
        })
1041
283k
    }
1042
1043
    /// Validates [`Payload::DataSection`](crate::Payload).
1044
    ///
1045
    /// This method should only be called when parsing a module.
1046
3.10k
    pub fn data_section(&mut self, section: &crate::DataSectionReader<'_>) -> Result<()> {
1047
3.10k
        self.process_module_section(
1048
3.10k
            section,
1049
3.10k
            "data",
1050
3.10k
            |_, _, count, offset| {
1051
3.10k
                check_max(0, count, MAX_WASM_DATA_SEGMENTS, "data segments", offset)
1052
3.10k
            },
1053
20.1k
            |state, types, d, offset| state.add_data_segment(d, types, offset),
1054
        )
1055
3.10k
    }
1056
1057
    /// Validates [`Payload::ModuleSection`](crate::Payload).
1058
    ///
1059
    /// This method should only be called when parsing a component.
1060
    #[cfg(feature = "component-model")]
1061
25.4k
    pub fn module_section(&mut self, range: &Range<usize>) -> Result<()> {
1062
25.4k
        self.state.ensure_component("module", range.start)?;
1063
1064
25.4k
        let current = self.components.last_mut().unwrap();
1065
25.4k
        check_max(
1066
25.4k
            current.core_modules.len(),
1067
            1,
1068
            MAX_WASM_MODULES,
1069
25.4k
            "modules",
1070
25.4k
            range.start,
1071
0
        )?;
1072
1073
25.4k
        match mem::replace(&mut self.state, State::Unparsed(Some(Encoding::Module))) {
1074
25.4k
            State::Component => {}
1075
0
            _ => unreachable!(),
1076
        }
1077
1078
25.4k
        Ok(())
1079
25.4k
    }
1080
1081
    /// Validates [`Payload::InstanceSection`](crate::Payload).
1082
    ///
1083
    /// This method should only be called when parsing a component.
1084
    #[cfg(feature = "component-model")]
1085
29.2k
    pub fn instance_section(&mut self, section: &crate::InstanceSectionReader) -> Result<()> {
1086
29.2k
        self.process_component_section(
1087
29.2k
            section,
1088
29.2k
            "core instance",
1089
29.2k
            |components, _, count, offset| {
1090
29.2k
                let current = components.last_mut().unwrap();
1091
29.2k
                check_max(
1092
29.2k
                    current.instance_count(),
1093
29.2k
                    count,
1094
                    MAX_WASM_INSTANCES,
1095
29.2k
                    "instances",
1096
29.2k
                    offset,
1097
0
                )?;
1098
29.2k
                current.core_instances.reserve(count as usize);
1099
29.2k
                Ok(())
1100
29.2k
            },
1101
45.7k
            |components, types, _features, instance, offset| {
1102
45.7k
                components
1103
45.7k
                    .last_mut()
1104
45.7k
                    .unwrap()
1105
45.7k
                    .add_core_instance(instance, types, offset)
1106
45.7k
            },
1107
        )
1108
29.2k
    }
1109
1110
    /// Validates [`Payload::CoreTypeSection`](crate::Payload).
1111
    ///
1112
    /// This method should only be called when parsing a component.
1113
    #[cfg(feature = "component-model")]
1114
0
    pub fn core_type_section(&mut self, section: &crate::CoreTypeSectionReader<'_>) -> Result<()> {
1115
0
        self.process_component_section(
1116
0
            section,
1117
0
            "core type",
1118
0
            |components, _types, count, offset| {
1119
0
                let current = components.last_mut().unwrap();
1120
0
                check_max(current.type_count(), count, MAX_WASM_TYPES, "types", offset)?;
1121
0
                current.core_types.reserve(count as usize);
1122
0
                Ok(())
1123
0
            },
1124
0
            |components, types, _features, ty, offset| {
1125
0
                ComponentState::add_core_type(
1126
0
                    components, ty, types, offset, false, /* checked above */
1127
                )
1128
0
            },
1129
        )
1130
0
    }
1131
1132
    /// Validates [`Payload::ComponentSection`](crate::Payload).
1133
    ///
1134
    /// This method should only be called when parsing a component.
1135
    #[cfg(feature = "component-model")]
1136
6.14k
    pub fn component_section(&mut self, range: &Range<usize>) -> Result<()> {
1137
6.14k
        self.state.ensure_component("component", range.start)?;
1138
1139
6.14k
        let current = self.components.last_mut().unwrap();
1140
6.14k
        check_max(
1141
6.14k
            current.components.len(),
1142
            1,
1143
            MAX_WASM_COMPONENTS,
1144
6.14k
            "components",
1145
6.14k
            range.start,
1146
0
        )?;
1147
1148
6.14k
        match mem::replace(&mut self.state, State::Unparsed(Some(Encoding::Component))) {
1149
6.14k
            State::Component => {}
1150
0
            _ => unreachable!(),
1151
        }
1152
1153
6.14k
        Ok(())
1154
6.14k
    }
1155
1156
    /// Validates [`Payload::ComponentInstanceSection`](crate::Payload).
1157
    ///
1158
    /// This method should only be called when parsing a component.
1159
    #[cfg(feature = "component-model")]
1160
6.14k
    pub fn component_instance_section(
1161
6.14k
        &mut self,
1162
6.14k
        section: &crate::ComponentInstanceSectionReader,
1163
6.14k
    ) -> Result<()> {
1164
6.14k
        self.process_component_section(
1165
6.14k
            section,
1166
6.14k
            "instance",
1167
6.14k
            |components, _, count, offset| {
1168
6.14k
                let current = components.last_mut().unwrap();
1169
6.14k
                check_max(
1170
6.14k
                    current.instance_count(),
1171
6.14k
                    count,
1172
                    MAX_WASM_INSTANCES,
1173
6.14k
                    "instances",
1174
6.14k
                    offset,
1175
0
                )?;
1176
6.14k
                current.instances.reserve(count as usize);
1177
6.14k
                Ok(())
1178
6.14k
            },
1179
6.14k
            |components, types, _features, instance, offset| {
1180
6.14k
                components
1181
6.14k
                    .last_mut()
1182
6.14k
                    .unwrap()
1183
6.14k
                    .add_instance(instance, types, offset)
1184
6.14k
            },
1185
        )
1186
6.14k
    }
1187
1188
    /// Validates [`Payload::ComponentAliasSection`](crate::Payload).
1189
    ///
1190
    /// This method should only be called when parsing a component.
1191
    #[cfg(feature = "component-model")]
1192
34.8k
    pub fn component_alias_section(
1193
34.8k
        &mut self,
1194
34.8k
        section: &crate::ComponentAliasSectionReader<'_>,
1195
34.8k
    ) -> Result<()> {
1196
34.8k
        self.process_component_section(
1197
34.8k
            section,
1198
34.8k
            "alias",
1199
34.8k
            |_, _, _, _| Ok(()), // maximums checked via `add_alias`
1200
65.4k
            |components, types, _features, alias, offset| -> Result<(), BinaryReaderError> {
1201
65.4k
                ComponentState::add_alias(components, alias, types, offset)
1202
65.4k
            },
1203
        )
1204
34.8k
    }
1205
1206
    /// Validates [`Payload::ComponentTypeSection`](crate::Payload).
1207
    ///
1208
    /// This method should only be called when parsing a component.
1209
    #[cfg(feature = "component-model")]
1210
137k
    pub fn component_type_section(
1211
137k
        &mut self,
1212
137k
        section: &crate::ComponentTypeSectionReader,
1213
137k
    ) -> Result<()> {
1214
137k
        self.process_component_section(
1215
137k
            section,
1216
137k
            "type",
1217
137k
            |components, _types, count, offset| {
1218
137k
                let current = components.last_mut().unwrap();
1219
137k
                check_max(current.type_count(), count, MAX_WASM_TYPES, "types", offset)?;
1220
137k
                current.types.reserve(count as usize);
1221
137k
                Ok(())
1222
137k
            },
1223
227k
            |components, types, _features, ty, offset| {
1224
227k
                ComponentState::add_type(
1225
227k
                    components, ty, types, offset, false, /* checked above */
1226
                )
1227
227k
            },
1228
        )
1229
137k
    }
1230
1231
    /// Validates [`Payload::ComponentCanonicalSection`](crate::Payload).
1232
    ///
1233
    /// This method should only be called when parsing a component.
1234
    #[cfg(feature = "component-model")]
1235
28.2k
    pub fn component_canonical_section(
1236
28.2k
        &mut self,
1237
28.2k
        section: &crate::ComponentCanonicalSectionReader,
1238
28.2k
    ) -> Result<()> {
1239
28.2k
        self.process_component_section(
1240
28.2k
            section,
1241
28.2k
            "function",
1242
28.2k
            |components, _, count, offset| {
1243
28.2k
                let current = components.last_mut().unwrap();
1244
28.2k
                check_max(
1245
28.2k
                    current.function_count(),
1246
28.2k
                    count,
1247
                    MAX_WASM_FUNCTIONS,
1248
28.2k
                    "functions",
1249
28.2k
                    offset,
1250
0
                )?;
1251
28.2k
                current.funcs.reserve(count as usize);
1252
28.2k
                Ok(())
1253
28.2k
            },
1254
52.3k
            |components, types, _features, func, offset| {
1255
52.3k
                let current = components.last_mut().unwrap();
1256
52.3k
                current.canonical_function(func, types, offset)
1257
52.3k
            },
1258
        )
1259
28.2k
    }
1260
1261
    /// Validates [`Payload::ComponentStartSection`](crate::Payload).
1262
    ///
1263
    /// This method should only be called when parsing a component.
1264
    #[cfg(feature = "component-model")]
1265
0
    pub fn component_start_section(
1266
0
        &mut self,
1267
0
        f: &crate::ComponentStartFunction,
1268
0
        range: &Range<usize>,
1269
0
    ) -> Result<()> {
1270
0
        self.state.ensure_component("start", range.start)?;
1271
1272
0
        self.components.last_mut().unwrap().add_start(
1273
0
            f.func_index,
1274
0
            &f.arguments,
1275
0
            f.results,
1276
0
            &mut self.types,
1277
0
            range.start,
1278
        )
1279
0
    }
1280
1281
    /// Validates [`Payload::ComponentImportSection`](crate::Payload).
1282
    ///
1283
    /// This method should only be called when parsing a component.
1284
    #[cfg(feature = "component-model")]
1285
19.6k
    pub fn component_import_section(
1286
19.6k
        &mut self,
1287
19.6k
        section: &crate::ComponentImportSectionReader,
1288
19.6k
    ) -> Result<()> {
1289
19.6k
        self.process_component_section(
1290
19.6k
            section,
1291
19.6k
            "import",
1292
19.6k
            |_, _, _, _| Ok(()), // add_import will check limits
1293
24.6k
            |components, types, _features, import, offset| {
1294
24.6k
                components
1295
24.6k
                    .last_mut()
1296
24.6k
                    .unwrap()
1297
24.6k
                    .add_import(import, types, offset)
1298
24.6k
            },
1299
        )
1300
19.6k
    }
1301
1302
    /// Validates [`Payload::ComponentExportSection`](crate::Payload).
1303
    ///
1304
    /// This method should only be called when parsing a component.
1305
    #[cfg(feature = "component-model")]
1306
118k
    pub fn component_export_section(
1307
118k
        &mut self,
1308
118k
        section: &crate::ComponentExportSectionReader,
1309
118k
    ) -> Result<()> {
1310
118k
        self.process_component_section(
1311
118k
            section,
1312
118k
            "export",
1313
118k
            |components, _, count, offset| {
1314
118k
                let current = components.last_mut().unwrap();
1315
118k
                check_max(
1316
118k
                    current.exports.len(),
1317
118k
                    count,
1318
                    MAX_WASM_EXPORTS,
1319
118k
                    "exports",
1320
118k
                    offset,
1321
0
                )?;
1322
118k
                current.exports.reserve(count as usize);
1323
118k
                Ok(())
1324
118k
            },
1325
123k
            |components, types, _features, export, offset| {
1326
123k
                let current = components.last_mut().unwrap();
1327
123k
                let ty = current.export_to_entity_type(&export, types, offset)?;
1328
123k
                current.add_export(
1329
123k
                    export.name,
1330
123k
                    ty,
1331
123k
                    types,
1332
123k
                    offset,
1333
                    false, /* checked above */
1334
                )
1335
123k
            },
1336
        )
1337
118k
    }
1338
1339
    /// Validates [`Payload::UnknownSection`](crate::Payload).
1340
    ///
1341
    /// Currently always returns an error.
1342
0
    pub fn unknown_section(&mut self, id: u8, range: &Range<usize>) -> Result<()> {
1343
0
        Err(format_err!(range.start, "malformed section id: {id}"))
1344
0
    }
1345
1346
    /// Validates [`Payload::End`](crate::Payload).
1347
    ///
1348
    /// Returns the types known to the validator for the module or component.
1349
70.7k
    pub fn end(&mut self, offset: usize) -> Result<Types> {
1350
70.7k
        match mem::replace(&mut self.state, State::End) {
1351
0
            State::Unparsed(_) => Err(BinaryReaderError::new(
1352
0
                "cannot call `end` before a header has been parsed",
1353
0
                offset,
1354
0
            )),
1355
0
            State::End => Err(BinaryReaderError::new(
1356
0
                "cannot call `end` after parsing has completed",
1357
0
                offset,
1358
0
            )),
1359
            State::Module => {
1360
41.4k
                let mut state = self.module.take().unwrap();
1361
1362
                // If there's a parent component, we'll add a module to the parent state
1363
                // and continue to validate the component
1364
                #[cfg(feature = "component-model")]
1365
41.4k
                if let Some(parent) = self.components.last_mut() {
1366
25.4k
                    parent.add_core_module(&state.module, &mut self.types, offset)?;
1367
25.4k
                    self.state = State::Component;
1368
15.9k
                }
1369
1370
41.4k
                Ok(Types::from_module(
1371
41.4k
                    self.id,
1372
41.4k
                    self.types.commit(),
1373
41.4k
                    state.module.arc().clone(),
1374
41.4k
                ))
1375
            }
1376
            #[cfg(feature = "component-model")]
1377
            State::Component => {
1378
29.3k
                let mut component = self.components.pop().unwrap();
1379
1380
                // Validate that all values were used for the component
1381
29.3k
                if let Some(index) = component.values.iter().position(|(_, used)| !*used) {
1382
0
                    bail!(
1383
0
                        offset,
1384
                        "value index {index} was not used as part of an \
1385
                         instantiation, start function, or export"
1386
                    );
1387
29.3k
                }
1388
1389
                // If there's a parent component, pop the stack, add it to the parent,
1390
                // and continue to validate the component
1391
29.3k
                let ty = component.finish(&self.types, offset)?;
1392
29.3k
                if let Some(parent) = self.components.last_mut() {
1393
6.14k
                    parent.add_component(ty, &mut self.types)?;
1394
6.14k
                    self.state = State::Component;
1395
23.1k
                }
1396
1397
29.3k
                Ok(Types::from_component(
1398
29.3k
                    self.id,
1399
29.3k
                    self.types.commit(),
1400
29.3k
                    component,
1401
29.3k
                ))
1402
            }
1403
        }
1404
70.7k
    }
1405
1406
157k
    fn process_module_section<'a, T>(
1407
157k
        &mut self,
1408
157k
        section: &SectionLimited<'a, T>,
1409
157k
        name: &str,
1410
157k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
157k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
157k
    ) -> Result<()>
1413
157k
    where
1414
157k
        T: FromReader<'a>,
1415
    {
1416
157k
        let offset = section.range().start;
1417
157k
        self.state.ensure_module(name, offset)?;
1418
1419
157k
        let state = self.module.as_mut().unwrap();
1420
1421
157k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
952k
        for item in section.clone().into_iter_with_offsets() {
1424
952k
            let (offset, item) = item?;
1425
952k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
157k
        Ok(())
1429
157k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::data::Data, <wasmparser::validator::Validator>::data_section::{closure#0}, <wasmparser::validator::Validator>::data_section::{closure#1}>
Line
Count
Source
1406
3.10k
    fn process_module_section<'a, T>(
1407
3.10k
        &mut self,
1408
3.10k
        section: &SectionLimited<'a, T>,
1409
3.10k
        name: &str,
1410
3.10k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
3.10k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
3.10k
    ) -> Result<()>
1413
3.10k
    where
1414
3.10k
        T: FromReader<'a>,
1415
    {
1416
3.10k
        let offset = section.range().start;
1417
3.10k
        self.state.ensure_module(name, offset)?;
1418
1419
3.10k
        let state = self.module.as_mut().unwrap();
1420
1421
3.10k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
20.1k
        for item in section.clone().into_iter_with_offsets() {
1424
20.1k
            let (offset, item) = item?;
1425
20.1k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
3.10k
        Ok(())
1429
3.10k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::types::MemoryType, <wasmparser::validator::Validator>::memory_section::{closure#0}, <wasmparser::validator::Validator>::memory_section::{closure#1}>
Line
Count
Source
1406
19.5k
    fn process_module_section<'a, T>(
1407
19.5k
        &mut self,
1408
19.5k
        section: &SectionLimited<'a, T>,
1409
19.5k
        name: &str,
1410
19.5k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
19.5k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
19.5k
    ) -> Result<()>
1413
19.5k
    where
1414
19.5k
        T: FromReader<'a>,
1415
    {
1416
19.5k
        let offset = section.range().start;
1417
19.5k
        self.state.ensure_module(name, offset)?;
1418
1419
19.5k
        let state = self.module.as_mut().unwrap();
1420
1421
19.5k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
47.5k
        for item in section.clone().into_iter_with_offsets() {
1424
47.5k
            let (offset, item) = item?;
1425
47.5k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
19.5k
        Ok(())
1429
19.5k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::types::TagType, <wasmparser::validator::Validator>::tag_section::{closure#0}, <wasmparser::validator::Validator>::tag_section::{closure#1}>
Line
Count
Source
1406
548
    fn process_module_section<'a, T>(
1407
548
        &mut self,
1408
548
        section: &SectionLimited<'a, T>,
1409
548
        name: &str,
1410
548
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
548
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
548
    ) -> Result<()>
1413
548
    where
1414
548
        T: FromReader<'a>,
1415
    {
1416
548
        let offset = section.range().start;
1417
548
        self.state.ensure_module(name, offset)?;
1418
1419
548
        let state = self.module.as_mut().unwrap();
1420
1421
548
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
8.79k
        for item in section.clone().into_iter_with_offsets() {
1424
8.79k
            let (offset, item) = item?;
1425
8.79k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
548
        Ok(())
1429
548
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::types::RecGroup, <wasmparser::validator::Validator>::type_section::{closure#0}, <wasmparser::validator::Validator>::type_section::{closure#1}>
Line
Count
Source
1406
40.1k
    fn process_module_section<'a, T>(
1407
40.1k
        &mut self,
1408
40.1k
        section: &SectionLimited<'a, T>,
1409
40.1k
        name: &str,
1410
40.1k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
40.1k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
40.1k
    ) -> Result<()>
1413
40.1k
    where
1414
40.1k
        T: FromReader<'a>,
1415
    {
1416
40.1k
        let offset = section.range().start;
1417
40.1k
        self.state.ensure_module(name, offset)?;
1418
1419
40.1k
        let state = self.module.as_mut().unwrap();
1420
1421
40.1k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
146k
        for item in section.clone().into_iter_with_offsets() {
1424
146k
            let (offset, item) = item?;
1425
146k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
40.1k
        Ok(())
1429
40.1k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::tables::Table, <wasmparser::validator::Validator>::table_section::{closure#0}, <wasmparser::validator::Validator>::table_section::{closure#1}>
Line
Count
Source
1406
7.46k
    fn process_module_section<'a, T>(
1407
7.46k
        &mut self,
1408
7.46k
        section: &SectionLimited<'a, T>,
1409
7.46k
        name: &str,
1410
7.46k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
7.46k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
7.46k
    ) -> Result<()>
1413
7.46k
    where
1414
7.46k
        T: FromReader<'a>,
1415
    {
1416
7.46k
        let offset = section.range().start;
1417
7.46k
        self.state.ensure_module(name, offset)?;
1418
1419
7.46k
        let state = self.module.as_mut().unwrap();
1420
1421
7.46k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
21.2k
        for item in section.clone().into_iter_with_offsets() {
1424
21.2k
            let (offset, item) = item?;
1425
21.2k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
7.46k
        Ok(())
1429
7.46k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::exports::Export, <wasmparser::validator::Validator>::export_section::{closure#0}, <wasmparser::validator::Validator>::export_section::{closure#1}>
Line
Count
Source
1406
21.1k
    fn process_module_section<'a, T>(
1407
21.1k
        &mut self,
1408
21.1k
        section: &SectionLimited<'a, T>,
1409
21.1k
        name: &str,
1410
21.1k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
21.1k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
21.1k
    ) -> Result<()>
1413
21.1k
    where
1414
21.1k
        T: FromReader<'a>,
1415
    {
1416
21.1k
        let offset = section.range().start;
1417
21.1k
        self.state.ensure_module(name, offset)?;
1418
1419
21.1k
        let state = self.module.as_mut().unwrap();
1420
1421
21.1k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
135k
        for item in section.clone().into_iter_with_offsets() {
1424
135k
            let (offset, item) = item?;
1425
135k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
21.1k
        Ok(())
1429
21.1k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::globals::Global, <wasmparser::validator::Validator>::global_section::{closure#0}, <wasmparser::validator::Validator>::global_section::{closure#1}>
Line
Count
Source
1406
8.94k
    fn process_module_section<'a, T>(
1407
8.94k
        &mut self,
1408
8.94k
        section: &SectionLimited<'a, T>,
1409
8.94k
        name: &str,
1410
8.94k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
8.94k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
8.94k
    ) -> Result<()>
1413
8.94k
    where
1414
8.94k
        T: FromReader<'a>,
1415
    {
1416
8.94k
        let offset = section.range().start;
1417
8.94k
        self.state.ensure_module(name, offset)?;
1418
1419
8.94k
        let state = self.module.as_mut().unwrap();
1420
1421
8.94k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
108k
        for item in section.clone().into_iter_with_offsets() {
1424
108k
            let (offset, item) = item?;
1425
108k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
8.94k
        Ok(())
1429
8.94k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::imports::Imports, <wasmparser::validator::Validator>::import_section::{closure#0}, <wasmparser::validator::Validator>::import_section::{closure#1}>
Line
Count
Source
1406
25.2k
    fn process_module_section<'a, T>(
1407
25.2k
        &mut self,
1408
25.2k
        section: &SectionLimited<'a, T>,
1409
25.2k
        name: &str,
1410
25.2k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
25.2k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
25.2k
    ) -> Result<()>
1413
25.2k
    where
1414
25.2k
        T: FromReader<'a>,
1415
    {
1416
25.2k
        let offset = section.range().start;
1417
25.2k
        self.state.ensure_module(name, offset)?;
1418
1419
25.2k
        let state = self.module.as_mut().unwrap();
1420
1421
25.2k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
145k
        for item in section.clone().into_iter_with_offsets() {
1424
145k
            let (offset, item) = item?;
1425
145k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
25.2k
        Ok(())
1429
25.2k
    }
<wasmparser::validator::Validator>::process_module_section::<wasmparser::readers::core::elements::Element, <wasmparser::validator::Validator>::element_section::{closure#0}, <wasmparser::validator::Validator>::element_section::{closure#1}>
Line
Count
Source
1406
6.01k
    fn process_module_section<'a, T>(
1407
6.01k
        &mut self,
1408
6.01k
        section: &SectionLimited<'a, T>,
1409
6.01k
        name: &str,
1410
6.01k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
6.01k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
6.01k
    ) -> Result<()>
1413
6.01k
    where
1414
6.01k
        T: FromReader<'a>,
1415
    {
1416
6.01k
        let offset = section.range().start;
1417
6.01k
        self.state.ensure_module(name, offset)?;
1418
1419
6.01k
        let state = self.module.as_mut().unwrap();
1420
1421
6.01k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
34.8k
        for item in section.clone().into_iter_with_offsets() {
1424
34.8k
            let (offset, item) = item?;
1425
34.8k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
6.01k
        Ok(())
1429
6.01k
    }
<wasmparser::validator::Validator>::process_module_section::<u32, <wasmparser::validator::Validator>::function_section::{closure#0}, <wasmparser::validator::Validator>::function_section::{closure#1}>
Line
Count
Source
1406
25.6k
    fn process_module_section<'a, T>(
1407
25.6k
        &mut self,
1408
25.6k
        section: &SectionLimited<'a, T>,
1409
25.6k
        name: &str,
1410
25.6k
        validate_section: impl FnOnce(&mut ModuleState, &mut TypeAlloc, u32, usize) -> Result<()>,
1411
25.6k
        mut validate_item: impl FnMut(&mut ModuleState, &mut TypeAlloc, T, usize) -> Result<()>,
1412
25.6k
    ) -> Result<()>
1413
25.6k
    where
1414
25.6k
        T: FromReader<'a>,
1415
    {
1416
25.6k
        let offset = section.range().start;
1417
25.6k
        self.state.ensure_module(name, offset)?;
1418
1419
25.6k
        let state = self.module.as_mut().unwrap();
1420
1421
25.6k
        validate_section(state, &mut self.types, section.count(), offset)?;
1422
1423
283k
        for item in section.clone().into_iter_with_offsets() {
1424
283k
            let (offset, item) = item?;
1425
283k
            validate_item(state, &mut self.types, item, offset)?;
1426
        }
1427
1428
25.6k
        Ok(())
1429
25.6k
    }
1430
1431
    #[cfg(feature = "component-model")]
1432
374k
    fn process_component_section<'a, T>(
1433
374k
        &mut self,
1434
374k
        section: &SectionLimited<'a, T>,
1435
374k
        name: &str,
1436
374k
        validate_section: impl FnOnce(
1437
374k
            &mut Vec<ComponentState>,
1438
374k
            &mut TypeAlloc,
1439
374k
            u32,
1440
374k
            usize,
1441
374k
        ) -> Result<()>,
1442
374k
        mut validate_item: impl FnMut(
1443
374k
            &mut Vec<ComponentState>,
1444
374k
            &mut TypeAlloc,
1445
374k
            &WasmFeatures,
1446
374k
            T,
1447
374k
            usize,
1448
374k
        ) -> Result<()>,
1449
374k
    ) -> Result<()>
1450
374k
    where
1451
374k
        T: FromReader<'a>,
1452
    {
1453
374k
        let offset = section.range().start;
1454
1455
374k
        self.state.ensure_component(name, offset)?;
1456
374k
        validate_section(
1457
374k
            &mut self.components,
1458
374k
            &mut self.types,
1459
374k
            section.count(),
1460
374k
            offset,
1461
374k
        )?;
1462
1463
545k
        for item in section.clone().into_iter_with_offsets() {
1464
545k
            let (offset, item) = item?;
1465
545k
            validate_item(
1466
545k
                &mut self.components,
1467
545k
                &mut self.types,
1468
545k
                &self.features,
1469
545k
                item,
1470
545k
                offset,
1471
545k
            )?;
1472
        }
1473
1474
374k
        Ok(())
1475
374k
    }
<wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::canonicals::CanonicalFunction, <wasmparser::validator::Validator>::component_canonical_section::{closure#0}, <wasmparser::validator::Validator>::component_canonical_section::{closure#1}>
Line
Count
Source
1432
28.2k
    fn process_component_section<'a, T>(
1433
28.2k
        &mut self,
1434
28.2k
        section: &SectionLimited<'a, T>,
1435
28.2k
        name: &str,
1436
28.2k
        validate_section: impl FnOnce(
1437
28.2k
            &mut Vec<ComponentState>,
1438
28.2k
            &mut TypeAlloc,
1439
28.2k
            u32,
1440
28.2k
            usize,
1441
28.2k
        ) -> Result<()>,
1442
28.2k
        mut validate_item: impl FnMut(
1443
28.2k
            &mut Vec<ComponentState>,
1444
28.2k
            &mut TypeAlloc,
1445
28.2k
            &WasmFeatures,
1446
28.2k
            T,
1447
28.2k
            usize,
1448
28.2k
        ) -> Result<()>,
1449
28.2k
    ) -> Result<()>
1450
28.2k
    where
1451
28.2k
        T: FromReader<'a>,
1452
    {
1453
28.2k
        let offset = section.range().start;
1454
1455
28.2k
        self.state.ensure_component(name, offset)?;
1456
28.2k
        validate_section(
1457
28.2k
            &mut self.components,
1458
28.2k
            &mut self.types,
1459
28.2k
            section.count(),
1460
28.2k
            offset,
1461
28.2k
        )?;
1462
1463
52.3k
        for item in section.clone().into_iter_with_offsets() {
1464
52.3k
            let (offset, item) = item?;
1465
52.3k
            validate_item(
1466
52.3k
                &mut self.components,
1467
52.3k
                &mut self.types,
1468
52.3k
                &self.features,
1469
52.3k
                item,
1470
52.3k
                offset,
1471
52.3k
            )?;
1472
        }
1473
1474
28.2k
        Ok(())
1475
28.2k
    }
<wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::types::ComponentType, <wasmparser::validator::Validator>::component_type_section::{closure#0}, <wasmparser::validator::Validator>::component_type_section::{closure#1}>
Line
Count
Source
1432
137k
    fn process_component_section<'a, T>(
1433
137k
        &mut self,
1434
137k
        section: &SectionLimited<'a, T>,
1435
137k
        name: &str,
1436
137k
        validate_section: impl FnOnce(
1437
137k
            &mut Vec<ComponentState>,
1438
137k
            &mut TypeAlloc,
1439
137k
            u32,
1440
137k
            usize,
1441
137k
        ) -> Result<()>,
1442
137k
        mut validate_item: impl FnMut(
1443
137k
            &mut Vec<ComponentState>,
1444
137k
            &mut TypeAlloc,
1445
137k
            &WasmFeatures,
1446
137k
            T,
1447
137k
            usize,
1448
137k
        ) -> Result<()>,
1449
137k
    ) -> Result<()>
1450
137k
    where
1451
137k
        T: FromReader<'a>,
1452
    {
1453
137k
        let offset = section.range().start;
1454
1455
137k
        self.state.ensure_component(name, offset)?;
1456
137k
        validate_section(
1457
137k
            &mut self.components,
1458
137k
            &mut self.types,
1459
137k
            section.count(),
1460
137k
            offset,
1461
137k
        )?;
1462
1463
227k
        for item in section.clone().into_iter_with_offsets() {
1464
227k
            let (offset, item) = item?;
1465
227k
            validate_item(
1466
227k
                &mut self.components,
1467
227k
                &mut self.types,
1468
227k
                &self.features,
1469
227k
                item,
1470
227k
                offset,
1471
227k
            )?;
1472
        }
1473
1474
137k
        Ok(())
1475
137k
    }
Unexecuted instantiation: <wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::types::CoreType, <wasmparser::validator::Validator>::core_type_section::{closure#0}, <wasmparser::validator::Validator>::core_type_section::{closure#1}>
<wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::aliases::ComponentAlias, <wasmparser::validator::Validator>::component_alias_section::{closure#0}, <wasmparser::validator::Validator>::component_alias_section::{closure#1}>
Line
Count
Source
1432
34.8k
    fn process_component_section<'a, T>(
1433
34.8k
        &mut self,
1434
34.8k
        section: &SectionLimited<'a, T>,
1435
34.8k
        name: &str,
1436
34.8k
        validate_section: impl FnOnce(
1437
34.8k
            &mut Vec<ComponentState>,
1438
34.8k
            &mut TypeAlloc,
1439
34.8k
            u32,
1440
34.8k
            usize,
1441
34.8k
        ) -> Result<()>,
1442
34.8k
        mut validate_item: impl FnMut(
1443
34.8k
            &mut Vec<ComponentState>,
1444
34.8k
            &mut TypeAlloc,
1445
34.8k
            &WasmFeatures,
1446
34.8k
            T,
1447
34.8k
            usize,
1448
34.8k
        ) -> Result<()>,
1449
34.8k
    ) -> Result<()>
1450
34.8k
    where
1451
34.8k
        T: FromReader<'a>,
1452
    {
1453
34.8k
        let offset = section.range().start;
1454
1455
34.8k
        self.state.ensure_component(name, offset)?;
1456
34.8k
        validate_section(
1457
34.8k
            &mut self.components,
1458
34.8k
            &mut self.types,
1459
34.8k
            section.count(),
1460
34.8k
            offset,
1461
34.8k
        )?;
1462
1463
65.4k
        for item in section.clone().into_iter_with_offsets() {
1464
65.4k
            let (offset, item) = item?;
1465
65.4k
            validate_item(
1466
65.4k
                &mut self.components,
1467
65.4k
                &mut self.types,
1468
65.4k
                &self.features,
1469
65.4k
                item,
1470
65.4k
                offset,
1471
65.4k
            )?;
1472
        }
1473
1474
34.8k
        Ok(())
1475
34.8k
    }
<wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::exports::ComponentExport, <wasmparser::validator::Validator>::component_export_section::{closure#0}, <wasmparser::validator::Validator>::component_export_section::{closure#1}>
Line
Count
Source
1432
118k
    fn process_component_section<'a, T>(
1433
118k
        &mut self,
1434
118k
        section: &SectionLimited<'a, T>,
1435
118k
        name: &str,
1436
118k
        validate_section: impl FnOnce(
1437
118k
            &mut Vec<ComponentState>,
1438
118k
            &mut TypeAlloc,
1439
118k
            u32,
1440
118k
            usize,
1441
118k
        ) -> Result<()>,
1442
118k
        mut validate_item: impl FnMut(
1443
118k
            &mut Vec<ComponentState>,
1444
118k
            &mut TypeAlloc,
1445
118k
            &WasmFeatures,
1446
118k
            T,
1447
118k
            usize,
1448
118k
        ) -> Result<()>,
1449
118k
    ) -> Result<()>
1450
118k
    where
1451
118k
        T: FromReader<'a>,
1452
    {
1453
118k
        let offset = section.range().start;
1454
1455
118k
        self.state.ensure_component(name, offset)?;
1456
118k
        validate_section(
1457
118k
            &mut self.components,
1458
118k
            &mut self.types,
1459
118k
            section.count(),
1460
118k
            offset,
1461
118k
        )?;
1462
1463
123k
        for item in section.clone().into_iter_with_offsets() {
1464
123k
            let (offset, item) = item?;
1465
123k
            validate_item(
1466
123k
                &mut self.components,
1467
123k
                &mut self.types,
1468
123k
                &self.features,
1469
123k
                item,
1470
123k
                offset,
1471
123k
            )?;
1472
        }
1473
1474
118k
        Ok(())
1475
118k
    }
<wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::imports::ComponentImport, <wasmparser::validator::Validator>::component_import_section::{closure#0}, <wasmparser::validator::Validator>::component_import_section::{closure#1}>
Line
Count
Source
1432
19.6k
    fn process_component_section<'a, T>(
1433
19.6k
        &mut self,
1434
19.6k
        section: &SectionLimited<'a, T>,
1435
19.6k
        name: &str,
1436
19.6k
        validate_section: impl FnOnce(
1437
19.6k
            &mut Vec<ComponentState>,
1438
19.6k
            &mut TypeAlloc,
1439
19.6k
            u32,
1440
19.6k
            usize,
1441
19.6k
        ) -> Result<()>,
1442
19.6k
        mut validate_item: impl FnMut(
1443
19.6k
            &mut Vec<ComponentState>,
1444
19.6k
            &mut TypeAlloc,
1445
19.6k
            &WasmFeatures,
1446
19.6k
            T,
1447
19.6k
            usize,
1448
19.6k
        ) -> Result<()>,
1449
19.6k
    ) -> Result<()>
1450
19.6k
    where
1451
19.6k
        T: FromReader<'a>,
1452
    {
1453
19.6k
        let offset = section.range().start;
1454
1455
19.6k
        self.state.ensure_component(name, offset)?;
1456
19.6k
        validate_section(
1457
19.6k
            &mut self.components,
1458
19.6k
            &mut self.types,
1459
19.6k
            section.count(),
1460
19.6k
            offset,
1461
19.6k
        )?;
1462
1463
24.6k
        for item in section.clone().into_iter_with_offsets() {
1464
24.6k
            let (offset, item) = item?;
1465
24.6k
            validate_item(
1466
24.6k
                &mut self.components,
1467
24.6k
                &mut self.types,
1468
24.6k
                &self.features,
1469
24.6k
                item,
1470
24.6k
                offset,
1471
24.6k
            )?;
1472
        }
1473
1474
19.6k
        Ok(())
1475
19.6k
    }
<wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::instances::ComponentInstance, <wasmparser::validator::Validator>::component_instance_section::{closure#0}, <wasmparser::validator::Validator>::component_instance_section::{closure#1}>
Line
Count
Source
1432
6.14k
    fn process_component_section<'a, T>(
1433
6.14k
        &mut self,
1434
6.14k
        section: &SectionLimited<'a, T>,
1435
6.14k
        name: &str,
1436
6.14k
        validate_section: impl FnOnce(
1437
6.14k
            &mut Vec<ComponentState>,
1438
6.14k
            &mut TypeAlloc,
1439
6.14k
            u32,
1440
6.14k
            usize,
1441
6.14k
        ) -> Result<()>,
1442
6.14k
        mut validate_item: impl FnMut(
1443
6.14k
            &mut Vec<ComponentState>,
1444
6.14k
            &mut TypeAlloc,
1445
6.14k
            &WasmFeatures,
1446
6.14k
            T,
1447
6.14k
            usize,
1448
6.14k
        ) -> Result<()>,
1449
6.14k
    ) -> Result<()>
1450
6.14k
    where
1451
6.14k
        T: FromReader<'a>,
1452
    {
1453
6.14k
        let offset = section.range().start;
1454
1455
6.14k
        self.state.ensure_component(name, offset)?;
1456
6.14k
        validate_section(
1457
6.14k
            &mut self.components,
1458
6.14k
            &mut self.types,
1459
6.14k
            section.count(),
1460
6.14k
            offset,
1461
6.14k
        )?;
1462
1463
6.14k
        for item in section.clone().into_iter_with_offsets() {
1464
6.14k
            let (offset, item) = item?;
1465
6.14k
            validate_item(
1466
6.14k
                &mut self.components,
1467
6.14k
                &mut self.types,
1468
6.14k
                &self.features,
1469
6.14k
                item,
1470
6.14k
                offset,
1471
6.14k
            )?;
1472
        }
1473
1474
6.14k
        Ok(())
1475
6.14k
    }
<wasmparser::validator::Validator>::process_component_section::<wasmparser::readers::component::instances::Instance, <wasmparser::validator::Validator>::instance_section::{closure#0}, <wasmparser::validator::Validator>::instance_section::{closure#1}>
Line
Count
Source
1432
29.2k
    fn process_component_section<'a, T>(
1433
29.2k
        &mut self,
1434
29.2k
        section: &SectionLimited<'a, T>,
1435
29.2k
        name: &str,
1436
29.2k
        validate_section: impl FnOnce(
1437
29.2k
            &mut Vec<ComponentState>,
1438
29.2k
            &mut TypeAlloc,
1439
29.2k
            u32,
1440
29.2k
            usize,
1441
29.2k
        ) -> Result<()>,
1442
29.2k
        mut validate_item: impl FnMut(
1443
29.2k
            &mut Vec<ComponentState>,
1444
29.2k
            &mut TypeAlloc,
1445
29.2k
            &WasmFeatures,
1446
29.2k
            T,
1447
29.2k
            usize,
1448
29.2k
        ) -> Result<()>,
1449
29.2k
    ) -> Result<()>
1450
29.2k
    where
1451
29.2k
        T: FromReader<'a>,
1452
    {
1453
29.2k
        let offset = section.range().start;
1454
1455
29.2k
        self.state.ensure_component(name, offset)?;
1456
29.2k
        validate_section(
1457
29.2k
            &mut self.components,
1458
29.2k
            &mut self.types,
1459
29.2k
            section.count(),
1460
29.2k
            offset,
1461
29.2k
        )?;
1462
1463
45.7k
        for item in section.clone().into_iter_with_offsets() {
1464
45.7k
            let (offset, item) = item?;
1465
45.7k
            validate_item(
1466
45.7k
                &mut self.components,
1467
45.7k
                &mut self.types,
1468
45.7k
                &self.features,
1469
45.7k
                item,
1470
45.7k
                offset,
1471
45.7k
            )?;
1472
        }
1473
1474
29.2k
        Ok(())
1475
29.2k
    }
1476
}
1477
1478
#[cfg(test)]
1479
mod tests {
1480
    use crate::{GlobalType, MemoryType, RefType, TableType, ValType, Validator, WasmFeatures};
1481
    use anyhow::Result;
1482
1483
    #[test]
1484
    fn test_module_type_information() -> Result<()> {
1485
        let bytes = wat::parse_str(
1486
            r#"
1487
            (module
1488
                (type (func (param i32 i64) (result i32)))
1489
                (memory 1 5)
1490
                (table 10 funcref)
1491
                (global (mut i32) (i32.const 0))
1492
                (func (type 0) (i32.const 0))
1493
                (tag (param i64 i32))
1494
                (elem funcref (ref.func 0))
1495
            )
1496
        "#,
1497
        )?;
1498
1499
        let mut validator =
1500
            Validator::new_with_features(WasmFeatures::default() | WasmFeatures::EXCEPTIONS);
1501
1502
        let types = validator.validate_all(&bytes)?;
1503
        let types = types.as_ref();
1504
1505
        assert_eq!(types.core_type_count_in_module(), 2);
1506
        assert_eq!(types.memory_count(), 1);
1507
        assert_eq!(types.table_count(), 1);
1508
        assert_eq!(types.global_count(), 1);
1509
        assert_eq!(types.function_count(), 1);
1510
        assert_eq!(types.tag_count(), 1);
1511
        assert_eq!(types.element_count(), 1);
1512
        assert_eq!(types.module_count(), 0);
1513
        assert_eq!(types.component_count(), 0);
1514
        assert_eq!(types.core_instance_count(), 0);
1515
        assert_eq!(types.value_count(), 0);
1516
1517
        let id = types.core_type_at_in_module(0);
1518
        let ty = types[id].unwrap_func();
1519
        assert_eq!(ty.params(), [ValType::I32, ValType::I64]);
1520
        assert_eq!(ty.results(), [ValType::I32]);
1521
1522
        let id = types.core_type_at_in_module(1);
1523
        let ty = types[id].unwrap_func();
1524
        assert_eq!(ty.params(), [ValType::I64, ValType::I32]);
1525
        assert_eq!(ty.results(), []);
1526
1527
        assert_eq!(
1528
            types.memory_at(0),
1529
            MemoryType {
1530
                memory64: false,
1531
                shared: false,
1532
                initial: 1,
1533
                maximum: Some(5),
1534
                page_size_log2: None,
1535
            }
1536
        );
1537
1538
        assert_eq!(
1539
            types.table_at(0),
1540
            TableType {
1541
                initial: 10,
1542
                maximum: None,
1543
                element_type: RefType::FUNCREF,
1544
                table64: false,
1545
                shared: false,
1546
            }
1547
        );
1548
1549
        assert_eq!(
1550
            types.global_at(0),
1551
            GlobalType {
1552
                content_type: ValType::I32,
1553
                mutable: true,
1554
                shared: false
1555
            }
1556
        );
1557
1558
        let id = types.core_function_at(0);
1559
        let ty = types[id].unwrap_func();
1560
        assert_eq!(ty.params(), [ValType::I32, ValType::I64]);
1561
        assert_eq!(ty.results(), [ValType::I32]);
1562
1563
        let ty = types.tag_at(0);
1564
        let ty = types[ty].unwrap_func();
1565
        assert_eq!(ty.params(), [ValType::I64, ValType::I32]);
1566
        assert_eq!(ty.results(), []);
1567
1568
        assert_eq!(types.element_at(0), RefType::FUNCREF);
1569
1570
        Ok(())
1571
    }
1572
1573
    #[test]
1574
    fn test_type_id_aliasing() -> Result<()> {
1575
        let bytes = wat::parse_str(
1576
            r#"
1577
            (component
1578
              (type $T (list string))
1579
              (alias outer 0 $T (type $A1))
1580
              (alias outer 0 $T (type $A2))
1581
            )
1582
        "#,
1583
        )?;
1584
1585
        let mut validator =
1586
            Validator::new_with_features(WasmFeatures::default() | WasmFeatures::COMPONENT_MODEL);
1587
1588
        let types = validator.validate_all(&bytes)?;
1589
        let types = types.as_ref();
1590
1591
        let t_id = types.component_defined_type_at(0);
1592
        let a1_id = types.component_defined_type_at(1);
1593
        let a2_id = types.component_defined_type_at(2);
1594
1595
        // The ids should all be the same
1596
        assert!(t_id == a1_id);
1597
        assert!(t_id == a2_id);
1598
        assert!(a1_id == a2_id);
1599
1600
        // However, they should all point to the same type
1601
        assert!(std::ptr::eq(&types[t_id], &types[a1_id],));
1602
        assert!(std::ptr::eq(&types[t_id], &types[a2_id],));
1603
1604
        Ok(())
1605
    }
1606
1607
    #[test]
1608
    fn test_type_id_exports() -> Result<()> {
1609
        let bytes = wat::parse_str(
1610
            r#"
1611
            (component
1612
              (type $T (list string))
1613
              (export $A1 "A1" (type $T))
1614
              (export $A2 "A2" (type $T))
1615
            )
1616
        "#,
1617
        )?;
1618
1619
        let mut validator =
1620
            Validator::new_with_features(WasmFeatures::default() | WasmFeatures::COMPONENT_MODEL);
1621
1622
        let types = validator.validate_all(&bytes)?;
1623
        let types = types.as_ref();
1624
1625
        let t_id = types.component_defined_type_at(0);
1626
        let a1_id = types.component_defined_type_at(1);
1627
        let a2_id = types.component_defined_type_at(2);
1628
1629
        // The ids should all be the same
1630
        assert!(t_id != a1_id);
1631
        assert!(t_id != a2_id);
1632
        assert!(a1_id != a2_id);
1633
1634
        // However, they should all point to the same type
1635
        assert!(std::ptr::eq(&types[t_id], &types[a1_id],));
1636
        assert!(std::ptr::eq(&types[t_id], &types[a2_id],));
1637
1638
        Ok(())
1639
    }
1640
1641
    #[test]
1642
    fn reset_fresh_validator() {
1643
        Validator::new().reset();
1644
    }
1645
}