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