Coverage Report

Created: 2025-12-04 07:01

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
    BinaryReaderError, FuncType, GlobalType, HeapType, MemoryType, RefType, SubType, TableType,
18
    ValType, 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.08M
    fn check_value_type(
83
3.08M
        &self,
84
3.08M
        t: &mut ValType,
85
3.08M
        features: &WasmFeatures,
86
3.08M
        offset: usize,
87
3.08M
    ) -> Result<(), BinaryReaderError> {
88
3.08M
        features
89
3.08M
            .check_value_type(*t)
90
3.08M
            .map_err(|s| BinaryReaderError::new(s, offset))?;
Unexecuted instantiation: <wasmparser::validator::core::ValidatorResources as wasmparser::resources::WasmModuleResources>::check_value_type::{closure#0}
Unexecuted instantiation: <wasmparser::validator::core::OperatorValidatorResources as wasmparser::resources::WasmModuleResources>::check_value_type::{closure#0}
91
3.08M
        match t {
92
196k
            ValType::Ref(r) => self.check_ref_type(r, offset),
93
2.88M
            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => Ok(()),
94
        }
95
3.08M
    }
<wasmparser::validator::core::ValidatorResources as wasmparser::resources::WasmModuleResources>::check_value_type
Line
Count
Source
82
3.08M
    fn check_value_type(
83
3.08M
        &self,
84
3.08M
        t: &mut ValType,
85
3.08M
        features: &WasmFeatures,
86
3.08M
        offset: usize,
87
3.08M
    ) -> Result<(), BinaryReaderError> {
88
3.08M
        features
89
3.08M
            .check_value_type(*t)
90
3.08M
            .map_err(|s| BinaryReaderError::new(s, offset))?;
91
3.08M
        match t {
92
196k
            ValType::Ref(r) => self.check_ref_type(r, offset),
93
2.88M
            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => Ok(()),
94
        }
95
3.08M
    }
Unexecuted instantiation: <wasmparser::validator::core::OperatorValidatorResources as wasmparser::resources::WasmModuleResources>::check_value_type
96
97
    /// Check and canonicalize a reference type.
98
197k
    fn check_ref_type(
99
197k
        &self,
100
197k
        ref_type: &mut RefType,
101
197k
        offset: usize,
102
197k
    ) -> Result<(), BinaryReaderError> {
103
197k
        let is_nullable = ref_type.is_nullable();
104
197k
        let mut heap_ty = ref_type.heap_type();
105
197k
        self.check_heap_type(&mut heap_ty, offset)?;
106
197k
        *ref_type = RefType::new(is_nullable, heap_ty).unwrap();
107
197k
        Ok(())
108
197k
    }
<wasmparser::validator::core::ValidatorResources as wasmparser::resources::WasmModuleResources>::check_ref_type
Line
Count
Source
98
197k
    fn check_ref_type(
99
197k
        &self,
100
197k
        ref_type: &mut RefType,
101
197k
        offset: usize,
102
197k
    ) -> Result<(), BinaryReaderError> {
103
197k
        let is_nullable = ref_type.is_nullable();
104
197k
        let mut heap_ty = ref_type.heap_type();
105
197k
        self.check_heap_type(&mut heap_ty, offset)?;
106
197k
        *ref_type = RefType::new(is_nullable, heap_ty).unwrap();
107
197k
        Ok(())
108
197k
    }
Unexecuted instantiation: <wasmparser::validator::core::OperatorValidatorResources as wasmparser::resources::WasmModuleResources>::check_ref_type
109
110
    /// Checks that a `HeapType` is valid and then additionally place it in its
111
    /// canonical form.
112
    ///
113
    /// Similar to `check_value_type` but for heap types.
114
    fn check_heap_type(
115
        &self,
116
        heap_type: &mut HeapType,
117
        offset: usize,
118
    ) -> Result<(), BinaryReaderError>;
119
120
    /// Get the top type for the given heap type.
121
    fn top_type(&self, heap_type: &HeapType) -> HeapType;
122
123
    /// Returns the number of elements.
124
    fn element_count(&self) -> u32;
125
126
    /// Returns the number of bytes in the Wasm data section.
127
    fn data_count(&self) -> Option<u32>;
128
129
    /// Returns whether the function index is referenced in the module anywhere
130
    /// outside of the start/function sections.
131
    fn is_function_referenced(&self, idx: u32) -> bool;
132
133
    /// Returns whether the function defined with the exact type.
134
    fn has_function_exact_type(&self, idx: u32) -> bool;
135
}
136
137
impl<T> WasmModuleResources for &'_ T
138
where
139
    T: ?Sized + WasmModuleResources,
140
{
141
    fn table_at(&self, at: u32) -> Option<TableType> {
142
        T::table_at(self, at)
143
    }
144
    fn memory_at(&self, at: u32) -> Option<MemoryType> {
145
        T::memory_at(self, at)
146
    }
147
    fn tag_at(&self, at: u32) -> Option<&FuncType> {
148
        T::tag_at(self, at)
149
    }
150
    fn global_at(&self, at: u32) -> Option<GlobalType> {
151
        T::global_at(self, at)
152
    }
153
    fn sub_type_at(&self, at: u32) -> Option<&SubType> {
154
        T::sub_type_at(self, at)
155
    }
156
    fn sub_type_at_id(&self, at: CoreTypeId) -> &SubType {
157
        T::sub_type_at_id(self, at)
158
    }
159
    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId> {
160
        T::type_id_of_function(self, func_idx)
161
    }
162
    fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
163
        T::type_index_of_function(self, func_idx)
164
    }
165
    fn check_heap_type(&self, t: &mut HeapType, offset: usize) -> Result<(), BinaryReaderError> {
166
        T::check_heap_type(self, t, offset)
167
    }
168
    fn top_type(&self, heap_type: &HeapType) -> HeapType {
169
        T::top_type(self, heap_type)
170
    }
171
    fn element_type_at(&self, at: u32) -> Option<RefType> {
172
        T::element_type_at(self, at)
173
    }
174
    fn is_subtype(&self, a: ValType, b: ValType) -> bool {
175
        T::is_subtype(self, a, b)
176
    }
177
310
    fn is_shared(&self, ty: RefType) -> bool {
178
310
        T::is_shared(self, ty)
179
310
    }
<&wasmparser::validator::core::ValidatorResources as wasmparser::resources::WasmModuleResources>::is_shared
Line
Count
Source
177
310
    fn is_shared(&self, ty: RefType) -> bool {
178
310
        T::is_shared(self, ty)
179
310
    }
Unexecuted instantiation: <&wasmparser::validator::core::OperatorValidatorResources as wasmparser::resources::WasmModuleResources>::is_shared
180
    fn element_count(&self) -> u32 {
181
        T::element_count(self)
182
    }
183
    fn data_count(&self) -> Option<u32> {
184
        T::data_count(self)
185
    }
186
    fn is_function_referenced(&self, idx: u32) -> bool {
187
        T::is_function_referenced(self, idx)
188
    }
189
    fn has_function_exact_type(&self, idx: u32) -> bool {
190
        T::has_function_exact_type(self, idx)
191
    }
192
}
193
194
impl<T> WasmModuleResources for alloc::sync::Arc<T>
195
where
196
    T: WasmModuleResources,
197
{
198
    fn table_at(&self, at: u32) -> Option<TableType> {
199
        T::table_at(self, at)
200
    }
201
202
    fn memory_at(&self, at: u32) -> Option<MemoryType> {
203
        T::memory_at(self, at)
204
    }
205
206
    fn tag_at(&self, at: u32) -> Option<&FuncType> {
207
        T::tag_at(self, at)
208
    }
209
210
    fn global_at(&self, at: u32) -> Option<GlobalType> {
211
        T::global_at(self, at)
212
    }
213
214
    fn sub_type_at(&self, type_idx: u32) -> Option<&SubType> {
215
        T::sub_type_at(self, type_idx)
216
    }
217
218
    fn sub_type_at_id(&self, id: CoreTypeId) -> &SubType {
219
        T::sub_type_at_id(self, id)
220
    }
221
222
    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId> {
223
        T::type_id_of_function(self, func_idx)
224
    }
225
226
    fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
227
        T::type_index_of_function(self, func_idx)
228
    }
229
230
    fn check_heap_type(&self, t: &mut HeapType, offset: usize) -> Result<(), BinaryReaderError> {
231
        T::check_heap_type(self, t, offset)
232
    }
233
234
    fn top_type(&self, heap_type: &HeapType) -> HeapType {
235
        T::top_type(self, heap_type)
236
    }
237
238
    fn element_type_at(&self, at: u32) -> Option<RefType> {
239
        T::element_type_at(self, at)
240
    }
241
242
    fn is_subtype(&self, a: ValType, b: ValType) -> bool {
243
        T::is_subtype(self, a, b)
244
    }
245
246
    fn is_shared(&self, ty: RefType) -> bool {
247
        T::is_shared(self, ty)
248
    }
249
250
    fn element_count(&self) -> u32 {
251
        T::element_count(self)
252
    }
253
254
    fn data_count(&self) -> Option<u32> {
255
        T::data_count(self)
256
    }
257
258
    fn is_function_referenced(&self, idx: u32) -> bool {
259
        T::is_function_referenced(self, idx)
260
    }
261
262
    fn has_function_exact_type(&self, idx: u32) -> bool {
263
        T::has_function_exact_type(self, idx)
264
    }
265
}