wasmparser/
resources.rs

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
16use crate::{
17    types::CoreTypeId, BinaryReaderError, FuncType, GlobalType, HeapType, MemoryType, RefType,
18    SubType, TableType, ValType, WasmFeatures,
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.
29pub 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 type ID associated with the given function index.
54    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId>;
55
56    /// Returns the type index associated with the given function index.
57    fn type_index_of_function(&self, func_index: u32) -> Option<u32>;
58
59    /// Returns the element type at the given index.
60    ///
61    /// The `RefType` must be canonicalized.
62    fn element_type_at(&self, at: u32) -> Option<RefType>;
63
64    /// Is `a` a subtype of `b`?
65    fn is_subtype(&self, a: ValType, b: ValType) -> bool;
66
67    /// Is the given reference type `shared`?
68    ///
69    /// While abstract heap types do carry along a `shared` flag, concrete heap
70    /// types do not. This function resolves those concrete heap types to
71    /// determine `shared`-ness.
72    fn is_shared(&self, ty: RefType) -> bool;
73
74    /// Check and canonicalize a value type.
75    ///
76    /// This will validate that `t` is valid under the `features` provided and
77    /// then additionally validate the structure of `t`. For example any type
78    /// references that `t` makes are validated and canonicalized.
79    fn check_value_type(
80        &self,
81        t: &mut ValType,
82        features: &WasmFeatures,
83        offset: usize,
84    ) -> Result<(), BinaryReaderError> {
85        features
86            .check_value_type(*t)
87            .map_err(|s| BinaryReaderError::new(s, offset))?;
88        match t {
89            ValType::Ref(r) => self.check_ref_type(r, offset),
90            ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 | ValType::V128 => Ok(()),
91        }
92    }
93
94    /// Check and canonicalize a reference type.
95    fn check_ref_type(
96        &self,
97        ref_type: &mut RefType,
98        offset: usize,
99    ) -> Result<(), BinaryReaderError> {
100        let is_nullable = ref_type.is_nullable();
101        let mut heap_ty = ref_type.heap_type();
102        self.check_heap_type(&mut heap_ty, offset)?;
103        *ref_type = RefType::new(is_nullable, heap_ty).unwrap();
104        Ok(())
105    }
106
107    /// Checks that a `HeapType` is valid and then additionally place it in its
108    /// canonical form.
109    ///
110    /// Similar to `check_value_type` but for heap types.
111    fn check_heap_type(
112        &self,
113        heap_type: &mut HeapType,
114        offset: usize,
115    ) -> Result<(), BinaryReaderError>;
116
117    /// Get the top type for the given heap type.
118    fn top_type(&self, heap_type: &HeapType) -> HeapType;
119
120    /// Returns the number of elements.
121    fn element_count(&self) -> u32;
122
123    /// Returns the number of bytes in the Wasm data section.
124    fn data_count(&self) -> Option<u32>;
125
126    /// Returns whether the function index is referenced in the module anywhere
127    /// outside of the start/function sections.
128    fn is_function_referenced(&self, idx: u32) -> bool;
129}
130
131impl<T> WasmModuleResources for &'_ T
132where
133    T: ?Sized + WasmModuleResources,
134{
135    fn table_at(&self, at: u32) -> Option<TableType> {
136        T::table_at(self, at)
137    }
138    fn memory_at(&self, at: u32) -> Option<MemoryType> {
139        T::memory_at(self, at)
140    }
141    fn tag_at(&self, at: u32) -> Option<&FuncType> {
142        T::tag_at(self, at)
143    }
144    fn global_at(&self, at: u32) -> Option<GlobalType> {
145        T::global_at(self, at)
146    }
147    fn sub_type_at(&self, at: u32) -> Option<&SubType> {
148        T::sub_type_at(self, at)
149    }
150    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId> {
151        T::type_id_of_function(self, func_idx)
152    }
153    fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
154        T::type_index_of_function(self, func_idx)
155    }
156    fn check_heap_type(&self, t: &mut HeapType, offset: usize) -> Result<(), BinaryReaderError> {
157        T::check_heap_type(self, t, offset)
158    }
159    fn top_type(&self, heap_type: &HeapType) -> HeapType {
160        T::top_type(self, heap_type)
161    }
162    fn element_type_at(&self, at: u32) -> Option<RefType> {
163        T::element_type_at(self, at)
164    }
165    fn is_subtype(&self, a: ValType, b: ValType) -> bool {
166        T::is_subtype(self, a, b)
167    }
168    fn is_shared(&self, ty: RefType) -> bool {
169        T::is_shared(self, ty)
170    }
171    fn element_count(&self) -> u32 {
172        T::element_count(self)
173    }
174    fn data_count(&self) -> Option<u32> {
175        T::data_count(self)
176    }
177    fn is_function_referenced(&self, idx: u32) -> bool {
178        T::is_function_referenced(self, idx)
179    }
180}
181
182impl<T> WasmModuleResources for alloc::sync::Arc<T>
183where
184    T: WasmModuleResources,
185{
186    fn table_at(&self, at: u32) -> Option<TableType> {
187        T::table_at(self, at)
188    }
189
190    fn memory_at(&self, at: u32) -> Option<MemoryType> {
191        T::memory_at(self, at)
192    }
193
194    fn tag_at(&self, at: u32) -> Option<&FuncType> {
195        T::tag_at(self, at)
196    }
197
198    fn global_at(&self, at: u32) -> Option<GlobalType> {
199        T::global_at(self, at)
200    }
201
202    fn sub_type_at(&self, type_idx: u32) -> Option<&SubType> {
203        T::sub_type_at(self, type_idx)
204    }
205
206    fn type_id_of_function(&self, func_idx: u32) -> Option<CoreTypeId> {
207        T::type_id_of_function(self, func_idx)
208    }
209
210    fn type_index_of_function(&self, func_idx: u32) -> Option<u32> {
211        T::type_index_of_function(self, func_idx)
212    }
213
214    fn check_heap_type(&self, t: &mut HeapType, offset: usize) -> Result<(), BinaryReaderError> {
215        T::check_heap_type(self, t, offset)
216    }
217
218    fn top_type(&self, heap_type: &HeapType) -> HeapType {
219        T::top_type(self, heap_type)
220    }
221
222    fn element_type_at(&self, at: u32) -> Option<RefType> {
223        T::element_type_at(self, at)
224    }
225
226    fn is_subtype(&self, a: ValType, b: ValType) -> bool {
227        T::is_subtype(self, a, b)
228    }
229
230    fn is_shared(&self, ty: RefType) -> bool {
231        T::is_shared(self, ty)
232    }
233
234    fn element_count(&self) -> u32 {
235        T::element_count(self)
236    }
237
238    fn data_count(&self) -> Option<u32> {
239        T::data_count(self)
240    }
241
242    fn is_function_referenced(&self, idx: u32) -> bool {
243        T::is_function_referenced(self, idx)
244    }
245}