Coverage Report

Created: 2024-10-16 07:58

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