Coverage Report

Created: 2026-10-31 07:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wasm-tools/crates/wasmparser/src/resources.rs
Line
Count
Source
1
/* Copyright 2019 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
    Error, FuncType, GlobalType, HeapType, MemoryType, RefType, SubType, TableType, ValType,
18
    WasmFeatures, types::CoreTypeId,
19
};
20
21
/// Types that qualify as Wasm validation database.
22
///
23
/// # Note
24
///
25
/// The `wasmparser` crate provides a builtin validation framework but allows
26
/// users of this crate to also feed the parsed Wasm into their own data
27
/// structure while parsing and also validate at the same time without
28
/// the need of an additional parsing or validation step or copying data around.
29
pub trait WasmModuleResources {
30
    /// Returns the table at given index if any.
31
    ///
32
    /// The table element type must be canonicalized.
33
    fn table_at(&self, at: u32) -> Option<TableType>;
34
35
    /// Returns the linear memory at given index.
36
    fn memory_at(&self, at: u32) -> Option<MemoryType>;
37
38
    /// Returns the tag at given index.
39
    ///
40
    /// The tag's function type must be canonicalized.
41
    fn tag_at(&self, at: u32) -> Option<&FuncType>;
42
43
    /// Returns the global variable at given index.
44
    ///
45
    /// The global's value type must be canonicalized.
46
    fn global_at(&self, at: u32) -> Option<GlobalType>;
47
48
    /// Returns the `SubType` associated with the given type index.
49
    ///
50
    /// The sub type must be canonicalized.
51
    fn sub_type_at(&self, type_index: u32) -> Option<&SubType>;
52
53
    /// Returns the `SubType` associated with the given core type id.
54
    fn sub_type_at_id(&self, id: CoreTypeId) -> &SubType;
55
56
    /// Returns the type ID associated with the given function index.
57
    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId>;
58
59
    /// Returns the type index associated with the given function index.
60
    fn type_index_of_function(&self, func_index: u32) -> Option<u32>;
61
62
    /// Returns the element type at the given index.
63
    ///
64
    /// The `RefType` must be canonicalized.
65
    fn element_type_at(&self, at: u32) -> Option<RefType>;
66
67
    /// Is `a` a subtype of `b`?
68
    fn is_subtype(&self, a: ValType, b: ValType) -> bool;
69
70
    /// Is the given reference type `shared`?
71
    ///
72
    /// While abstract heap types do carry along a `shared` flag, concrete heap
73
    /// types do not. This function resolves those concrete heap types to
74
    /// determine `shared`-ness.
75
    fn is_shared(&self, ty: RefType) -> bool;
76
77
    /// Check and canonicalize a value type.
78
    ///
79
    /// This will validate that `t` is valid under the `features` provided and
80
    /// then additionally validate the structure of `t`. For example any type
81
    /// references that `t` makes are validated and canonicalized.
82
3.91M
    fn check_value_type(
83
3.91M
        &self,
84
3.91M
        t: &mut ValType,
85
3.91M
        features: &WasmFeatures,
86
3.91M
        offset: u64,
87
3.91M
    ) -> Result<(), Error> {
88
3.91M
        features.check_value_type(*t, offset)?;
89
3.91M
        match t {
90
390k
            ValType::Ref(r) => self.check_ref_type(r, offset),
91
3.52M
            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => Ok(()),
92
        }
93
3.91M
    }
<wasmparser::validator::core::ValidatorResources as wasmparser::resources::WasmModuleResources>::check_value_type
Line
Count
Source
82
3.91M
    fn check_value_type(
83
3.91M
        &self,
84
3.91M
        t: &mut ValType,
85
3.91M
        features: &WasmFeatures,
86
3.91M
        offset: u64,
87
3.91M
    ) -> Result<(), Error> {
88
3.91M
        features.check_value_type(*t, offset)?;
89
3.91M
        match t {
90
390k
            ValType::Ref(r) => self.check_ref_type(r, offset),
91
3.52M
            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => Ok(()),
92
        }
93
3.91M
    }
Unexecuted instantiation: <wasmparser::validator::core::OperatorValidatorResources as wasmparser::resources::WasmModuleResources>::check_value_type
94
95
    /// Check and canonicalize a reference type.
96
393k
    fn check_ref_type(&self, ref_type: &mut RefType, offset: u64) -> Result<(), Error> {
97
393k
        let is_nullable = ref_type.is_nullable();
98
393k
        let mut heap_ty = ref_type.heap_type();
99
393k
        self.check_heap_type(&mut heap_ty, offset)?;
100
393k
        *ref_type = RefType::new(is_nullable, heap_ty).unwrap();
101
393k
        Ok(())
102
393k
    }
<wasmparser::validator::core::ValidatorResources as wasmparser::resources::WasmModuleResources>::check_ref_type
Line
Count
Source
96
393k
    fn check_ref_type(&self, ref_type: &mut RefType, offset: u64) -> Result<(), Error> {
97
393k
        let is_nullable = ref_type.is_nullable();
98
393k
        let mut heap_ty = ref_type.heap_type();
99
393k
        self.check_heap_type(&mut heap_ty, offset)?;
100
393k
        *ref_type = RefType::new(is_nullable, heap_ty).unwrap();
101
393k
        Ok(())
102
393k
    }
Unexecuted instantiation: <wasmparser::validator::core::OperatorValidatorResources as wasmparser::resources::WasmModuleResources>::check_ref_type
103
104
    /// Checks that a `HeapType` is valid and then additionally place it in its
105
    /// canonical form.
106
    ///
107
    /// Similar to `check_value_type` but for heap types.
108
    fn check_heap_type(&self, heap_type: &mut HeapType, offset: u64) -> Result<(), Error>;
109
110
    /// Get the top type for the given heap type.
111
    fn top_type(&self, heap_type: &HeapType) -> HeapType;
112
113
    /// Returns the number of elements.
114
    fn element_count(&self) -> u32;
115
116
    /// Returns the number of bytes in the Wasm data section.
117
    fn data_count(&self) -> Option<u32>;
118
119
    /// Returns whether the function index is referenced in the module anywhere
120
    /// outside of the start/function sections.
121
    fn is_function_referenced(&self, idx: u32) -> bool;
122
123
    /// Returns whether the function defined with the exact type.
124
    fn has_function_exact_type(&self, idx: u32) -> bool;
125
}
126
127
impl<T> WasmModuleResources for &'_ T
128
where
129
    T: ?Sized + WasmModuleResources,
130
{
131
0
    fn table_at(&self, at: u32) -> Option<TableType> {
132
0
        T::table_at(self, at)
133
0
    }
134
0
    fn memory_at(&self, at: u32) -> Option<MemoryType> {
135
0
        T::memory_at(self, at)
136
0
    }
137
0
    fn tag_at(&self, at: u32) -> Option<&FuncType> {
138
0
        T::tag_at(self, at)
139
0
    }
140
0
    fn global_at(&self, at: u32) -> Option<GlobalType> {
141
0
        T::global_at(self, at)
142
0
    }
143
0
    fn sub_type_at(&self, at: u32) -> Option<&SubType> {
144
0
        T::sub_type_at(self, at)
145
0
    }
146
0
    fn sub_type_at_id(&self, at: CoreTypeId) -> &SubType {
147
0
        T::sub_type_at_id(self, at)
148
0
    }
149
0
    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId> {
150
0
        T::type_id_of_function(self, func_idx)
151
0
    }
152
0
    fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
153
0
        T::type_index_of_function(self, func_idx)
154
0
    }
155
0
    fn check_heap_type(&self, t: &mut HeapType, offset: u64) -> Result<(), Error> {
156
0
        T::check_heap_type(self, t, offset)
157
0
    }
158
0
    fn top_type(&self, heap_type: &HeapType) -> HeapType {
159
0
        T::top_type(self, heap_type)
160
0
    }
161
0
    fn element_type_at(&self, at: u32) -> Option<RefType> {
162
0
        T::element_type_at(self, at)
163
0
    }
164
0
    fn is_subtype(&self, a: ValType, b: ValType) -> bool {
165
0
        T::is_subtype(self, a, b)
166
0
    }
167
325
    fn is_shared(&self, ty: RefType) -> bool {
168
325
        T::is_shared(self, ty)
169
325
    }
<&wasmparser::validator::core::ValidatorResources as wasmparser::resources::WasmModuleResources>::is_shared
Line
Count
Source
167
325
    fn is_shared(&self, ty: RefType) -> bool {
168
325
        T::is_shared(self, ty)
169
325
    }
Unexecuted instantiation: <&wasmparser::validator::core::OperatorValidatorResources as wasmparser::resources::WasmModuleResources>::is_shared
170
0
    fn element_count(&self) -> u32 {
171
0
        T::element_count(self)
172
0
    }
173
0
    fn data_count(&self) -> Option<u32> {
174
0
        T::data_count(self)
175
0
    }
176
0
    fn is_function_referenced(&self, idx: u32) -> bool {
177
0
        T::is_function_referenced(self, idx)
178
0
    }
179
0
    fn has_function_exact_type(&self, idx: u32) -> bool {
180
0
        T::has_function_exact_type(self, idx)
181
0
    }
182
}
183
184
impl<T> WasmModuleResources for alloc::sync::Arc<T>
185
where
186
    T: WasmModuleResources,
187
{
188
0
    fn table_at(&self, at: u32) -> Option<TableType> {
189
0
        T::table_at(self, at)
190
0
    }
191
192
0
    fn memory_at(&self, at: u32) -> Option<MemoryType> {
193
0
        T::memory_at(self, at)
194
0
    }
195
196
0
    fn tag_at(&self, at: u32) -> Option<&FuncType> {
197
0
        T::tag_at(self, at)
198
0
    }
199
200
0
    fn global_at(&self, at: u32) -> Option<GlobalType> {
201
0
        T::global_at(self, at)
202
0
    }
203
204
0
    fn sub_type_at(&self, type_idx: u32) -> Option<&SubType> {
205
0
        T::sub_type_at(self, type_idx)
206
0
    }
207
208
0
    fn sub_type_at_id(&self, id: CoreTypeId) -> &SubType {
209
0
        T::sub_type_at_id(self, id)
210
0
    }
211
212
0
    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId> {
213
0
        T::type_id_of_function(self, func_idx)
214
0
    }
215
216
0
    fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
217
0
        T::type_index_of_function(self, func_idx)
218
0
    }
219
220
0
    fn check_heap_type(&self, t: &mut HeapType, offset: u64) -> Result<(), Error> {
221
0
        T::check_heap_type(self, t, offset)
222
0
    }
223
224
0
    fn top_type(&self, heap_type: &HeapType) -> HeapType {
225
0
        T::top_type(self, heap_type)
226
0
    }
227
228
0
    fn element_type_at(&self, at: u32) -> Option<RefType> {
229
0
        T::element_type_at(self, at)
230
0
    }
231
232
0
    fn is_subtype(&self, a: ValType, b: ValType) -> bool {
233
0
        T::is_subtype(self, a, b)
234
0
    }
235
236
0
    fn is_shared(&self, ty: RefType) -> bool {
237
0
        T::is_shared(self, ty)
238
0
    }
239
240
0
    fn element_count(&self) -> u32 {
241
0
        T::element_count(self)
242
0
    }
243
244
0
    fn data_count(&self) -> Option<u32> {
245
0
        T::data_count(self)
246
0
    }
247
248
0
    fn is_function_referenced(&self, idx: u32) -> bool {
249
0
        T::is_function_referenced(self, idx)
250
0
    }
251
252
0
    fn has_function_exact_type(&self, idx: u32) -> bool {
253
0
        T::has_function_exact_type(self, idx)
254
0
    }
255
}