Coverage Report

Created: 2026-08-02 07:35

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