Coverage Report

Created: 2021-03-22 08:29

/src/wasm-tools/crates/wasmparser/src/module_resources.rs
Line
Count
Source (jump to first uncovered line)
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::{FuncType, GlobalType, MemoryType, TableType, Type};
17
use std::ops::Range;
18
19
/// Types that qualify as Wasm function types for validation purposes.
20
pub trait WasmFuncType {
21
    /// Returns the number of input types.
22
    fn len_inputs(&self) -> usize;
23
    /// Returns the number of output types.
24
    fn len_outputs(&self) -> usize;
25
    /// Returns the type at given index if any.
26
    ///
27
    /// # Note
28
    ///
29
    /// The returned type may be wrapped by the user crate and thus
30
    /// the actually returned type only has to be comparable to a Wasm type.
31
    fn input_at(&self, at: u32) -> Option<Type>;
32
    /// Returns the type at given index if any.
33
    ///
34
    /// # Note
35
    ///
36
    /// The returned type may be wrapped by the user crate and thus
37
    /// the actually returned type only has to be comparable to a Wasm type.
38
    fn output_at(&self, at: u32) -> Option<Type>;
39
40
    /// Returns the list of inputs as an iterator.
41
2.00M
    fn inputs(&self) -> WasmFuncTypeInputs<'_, Self>
42
2.00M
    where
43
2.00M
        Self: Sized,
44
2.00M
    {
45
2.00M
        WasmFuncTypeInputs {
46
2.00M
            func_type: self,
47
2.00M
            range: 0..self.len_inputs() as u32,
48
2.00M
        }
49
2.00M
    }
50
51
    /// Returns the list of outputs as an iterator.
52
3.56M
    fn outputs(&self) -> WasmFuncTypeOutputs<'_, Self>
53
3.56M
    where
54
3.56M
        Self: Sized,
55
3.56M
    {
56
3.56M
        WasmFuncTypeOutputs {
57
3.56M
            func_type: self,
58
3.56M
            range: 0..self.len_outputs() as u32,
59
3.56M
        }
60
3.56M
    }
61
}
62
63
impl<T> WasmFuncType for &'_ T
64
where
65
    T: ?Sized + WasmFuncType,
66
{
67
0
    fn len_inputs(&self) -> usize {
68
0
        T::len_inputs(self)
69
0
    }
70
0
    fn len_outputs(&self) -> usize {
71
0
        T::len_outputs(self)
72
0
    }
73
0
    fn input_at(&self, at: u32) -> Option<Type> {
74
0
        T::input_at(self, at)
75
0
    }
76
0
    fn output_at(&self, at: u32) -> Option<Type> {
77
0
        T::output_at(self, at)
78
0
    }
79
}
80
81
/// Iterator over the inputs of a Wasm function type.
82
pub struct WasmFuncTypeInputs<'a, T> {
83
    /// The iterated-over function type.
84
    func_type: &'a T,
85
    /// The range we're iterating over.
86
    range: Range<u32>,
87
}
88
89
impl<T> Iterator for WasmFuncTypeInputs<'_, T>
90
where
91
    T: WasmFuncType,
92
{
93
    type Item = crate::Type;
94
95
8.86M
    fn next(&mut self) -> Option<Self::Item> {
96
8.86M
        self.range
97
8.86M
            .next()
98
8.86M
            .map(|i| self.func_type.input_at(i).unwrap())
99
8.86M
    }
100
101
996k
    fn size_hint(&self) -> (usize, Option<usize>) {
102
996k
        self.range.size_hint()
103
996k
    }
104
}
105
106
impl<T> DoubleEndedIterator for WasmFuncTypeInputs<'_, T>
107
where
108
    T: WasmFuncType,
109
{
110
319k
    fn next_back(&mut self) -> Option<Self::Item> {
111
319k
        self.range
112
319k
            .next_back()
113
319k
            .map(|i| self.func_type.input_at(i).unwrap())
114
319k
    }
115
}
116
117
impl<T> ExactSizeIterator for WasmFuncTypeInputs<'_, T>
118
where
119
    T: WasmFuncType,
120
{
121
0
    fn len(&self) -> usize {
122
0
        self.range.len()
123
0
    }
124
}
125
126
impl<'a, T> Clone for WasmFuncTypeInputs<'a, T> {
127
0
    fn clone(&self) -> WasmFuncTypeInputs<'a, T> {
128
0
        WasmFuncTypeInputs {
129
0
            func_type: self.func_type,
130
0
            range: self.range.clone(),
131
0
        }
132
0
    }
133
}
134
135
/// Iterator over the outputs of a Wasm function type.
136
pub struct WasmFuncTypeOutputs<'a, T> {
137
    /// The iterated-over function type.
138
    func_type: &'a T,
139
    /// The range we're iterating over.
140
    range: Range<u32>,
141
}
142
143
impl<T> Iterator for WasmFuncTypeOutputs<'_, T>
144
where
145
    T: WasmFuncType,
146
{
147
    type Item = crate::Type;
148
149
10.2M
    fn next(&mut self) -> Option<Self::Item> {
150
10.2M
        self.range
151
10.2M
            .next()
152
10.2M
            .map(|i| self.func_type.output_at(i).unwrap())
153
10.2M
    }
154
155
0
    fn size_hint(&self) -> (usize, Option<usize>) {
156
0
        self.range.size_hint()
157
0
    }
158
}
159
160
impl<T> DoubleEndedIterator for WasmFuncTypeOutputs<'_, T>
161
where
162
    T: WasmFuncType,
163
{
164
8.49M
    fn next_back(&mut self) -> Option<Self::Item> {
165
8.49M
        self.range
166
8.49M
            .next_back()
167
8.49M
            .map(|i| self.func_type.output_at(i).unwrap())
168
8.49M
    }
169
}
170
171
impl<T> ExactSizeIterator for WasmFuncTypeOutputs<'_, T>
172
where
173
    T: WasmFuncType,
174
{
175
    fn len(&self) -> usize {
176
        self.range.len()
177
    }
178
}
179
180
impl<'a, T> Clone for WasmFuncTypeOutputs<'a, T> {
181
0
    fn clone(&self) -> WasmFuncTypeOutputs<'a, T> {
182
0
        WasmFuncTypeOutputs {
183
0
            func_type: self.func_type,
184
0
            range: self.range.clone(),
185
0
        }
186
0
    }
187
}
188
189
/// Types  that qualify as Wasm valiation database.
190
///
191
/// # Note
192
///
193
/// The `wasmparser` crate provides a builtin validation framework but allows
194
/// users of this crate to also feed the parsed Wasm into their own data
195
/// structure while parsing and also validate at the same time without
196
/// the need of an additional parsing or validation step or copying data around.
197
pub trait WasmModuleResources {
198
    /// The function type used for validation.
199
    type FuncType: WasmFuncType;
200
201
    /// Returns the table at given index if any.
202
    fn table_at(&self, at: u32) -> Option<TableType>;
203
    /// Returns the linear memory at given index.
204
    fn memory_at(&self, at: u32) -> Option<MemoryType>;
205
    /// Returns the event at given index.
206
    fn event_at(&self, at: u32) -> Option<&Self::FuncType>;
207
    /// Returns the global variable at given index.
208
    fn global_at(&self, at: u32) -> Option<GlobalType>;
209
    /// Returns the `FuncType` associated with the given type index.
210
    fn func_type_at(&self, type_idx: u32) -> Option<&Self::FuncType>;
211
    /// Returns the `FuncType` associated with the given function index.
212
    fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType>;
213
    /// Returns the element type at the given index.
214
    fn element_type_at(&self, at: u32) -> Option<Type>;
215
216
    /// Returns the number of elements.
217
    fn element_count(&self) -> u32;
218
    /// Returns the number of bytes in the Wasm data section.
219
    fn data_count(&self) -> u32;
220
    /// Returns whether the function index is referenced in the module anywhere
221
    /// outside of the start/function sections.
222
    fn is_function_referenced(&self, idx: u32) -> bool;
223
}
224
225
impl<T> WasmModuleResources for &'_ T
226
where
227
    T: ?Sized + WasmModuleResources,
228
{
229
    type FuncType = T::FuncType;
230
231
0
    fn table_at(&self, at: u32) -> Option<TableType> {
232
0
        T::table_at(self, at)
233
0
    }
234
545k
    fn memory_at(&self, at: u32) -> Option<MemoryType> {
235
545k
        T::memory_at(self, at)
236
545k
    }
237
34
    fn event_at(&self, at: u32) -> Option<&Self::FuncType> {
238
34
        T::event_at(self, at)
239
34
    }
240
0
    fn global_at(&self, at: u32) -> Option<GlobalType> {
241
0
        T::global_at(self, at)
242
0
    }
243
128k
    fn func_type_at(&self, at: u32) -> Option<&Self::FuncType> {
244
128k
        T::func_type_at(self, at)
245
128k
    }
246
0
    fn type_of_function(&self, func_idx: u32) -> Option<&Self::FuncType> {
247
0
        T::type_of_function(self, func_idx)
248
0
    }
249
0
    fn element_type_at(&self, at: u32) -> Option<Type> {
250
0
        T::element_type_at(self, at)
251
0
    }
252
253
0
    fn element_count(&self) -> u32 {
254
0
        T::element_count(self)
255
0
    }
256
0
    fn data_count(&self) -> u32 {
257
0
        T::data_count(self)
258
0
    }
259
0
    fn is_function_referenced(&self, idx: u32) -> bool {
260
0
        T::is_function_referenced(self, idx)
261
0
    }
262
}
263
264
impl WasmFuncType for FuncType {
265
2.00M
    fn len_inputs(&self) -> usize {
266
2.00M
        self.params.len()
267
2.00M
    }
268
269
3.56M
    fn len_outputs(&self) -> usize {
270
3.56M
        self.returns.len()
271
3.56M
    }
272
273
7.18M
    fn input_at(&self, at: u32) -> Option<Type> {
274
7.18M
        self.params.get(at as usize).copied()
275
7.18M
    }
276
277
15.1M
    fn output_at(&self, at: u32) -> Option<Type> {
278
15.1M
        self.returns.get(at as usize).copied()
279
15.1M
    }
280
}