wasm/validation/modules/
indices.rs

1use crate::{
2    core::{
3        decoding::reader::WasmDecoder,
4        structure::modules::indices::{
5            DataIdx, ElemIdx, FuncIdx, GlobalIdx, Idx, IdxVec, LocalIdx, MemIdx, TableIdx, TypeIdx,
6        },
7    },
8    FuncType, ValType, ValidationError,
9};
10
11impl TypeIdx {
12    /// Validates that a given index is a valid type index.
13    ///
14    /// On success a new [`TypeIdx`] is returned, otherwise a
15    /// [`ValidationError`] is returned.
16    pub fn validate(
17        index: u32,
18        c_types: &IdxVec<TypeIdx, FuncType>,
19    ) -> Result<Self, ValidationError> {
20        c_types
21            .validate_index(index)
22            .ok_or(ValidationError::InvalidTypeIdx(index))
23    }
24
25    /// Reads a type index from Wasm code and validates that it is a valid index
26    /// for a given types vector.
27    pub fn decode_and_validate(
28        wasm: &mut WasmDecoder,
29        c_types: &IdxVec<TypeIdx, FuncType>,
30    ) -> Result<Self, ValidationError> {
31        let index = wasm.decode_var_u32()?;
32        Self::validate(index, c_types)
33    }
34}
35
36impl FuncIdx {
37    /// Validates that a given index is a valid function index.
38    ///
39    /// On success a new [`FuncIdx`] is returned, otherwise a
40    /// [`ValidationError`] is returned.
41    pub fn validate<T>(index: u32, c_funcs: &IdxVec<FuncIdx, T>) -> Result<Self, ValidationError> {
42        c_funcs
43            .validate_index(index)
44            .ok_or(ValidationError::InvalidFuncIdx(index))
45    }
46
47    /// Reads a function index from Wasm code and validates that it is a valid
48    /// index for a given functions vector.
49    pub fn decode_and_validate<T>(
50        wasm: &mut WasmDecoder,
51        c_funcs: &IdxVec<FuncIdx, T>,
52    ) -> Result<Self, ValidationError> {
53        let index = wasm.decode_var_u32()?;
54        Self::validate(index, c_funcs)
55    }
56}
57
58impl TableIdx {
59    /// Validates that a given index is a valid table index.
60    ///
61    /// On success a new [`TableIdx`] is returned, otherwise a
62    /// [`ValidationError`] is returned.
63    pub fn validate<T>(
64        index: u32,
65        c_tables: &IdxVec<TableIdx, T>,
66    ) -> Result<Self, ValidationError> {
67        c_tables
68            .validate_index(index)
69            .ok_or(ValidationError::InvalidTableIdx(index))
70    }
71
72    /// Reads a table index from Wasm code and validates that it is a valid
73    /// index for a given tables vector.
74    pub fn decode_and_validate<T>(
75        wasm: &mut WasmDecoder,
76        c_tables: &IdxVec<TableIdx, T>,
77    ) -> Result<Self, ValidationError> {
78        let index = wasm.decode_var_u32()?;
79        Self::validate(index, c_tables)
80    }
81}
82
83impl MemIdx {
84    /// Validates that a given index is a valid memory index.
85    ///
86    /// On success a new [`MemIdx`] is returned, otherwise a [`ValidationError`]
87    /// is returned.
88    pub fn validate<T>(index: u32, c_mems: &IdxVec<MemIdx, T>) -> Result<Self, ValidationError> {
89        c_mems
90            .validate_index(index)
91            .ok_or(ValidationError::InvalidMemIdx(index))
92    }
93
94    /// Reads a memory index from Wasm code and validates that it is a valid
95    /// index for a given memories vector.
96    pub fn decode_and_validate<T>(
97        wasm: &mut WasmDecoder,
98        c_mems: &IdxVec<MemIdx, T>,
99    ) -> Result<Self, ValidationError> {
100        let index = wasm.decode_var_u32()?;
101        Self::validate(index, c_mems)
102    }
103}
104
105impl GlobalIdx {
106    /// Validates that a given index is a valid global index.
107    ///
108    /// On success a new [`GlobalIdx`] is returned, otherwise a
109    /// [`ValidationError`] is returned.
110    pub fn validate<T>(
111        index: u32,
112        c_globals: &IdxVec<GlobalIdx, T>,
113    ) -> Result<Self, ValidationError> {
114        c_globals
115            .validate_index(index)
116            .ok_or(ValidationError::InvalidGlobalIdx(index))
117    }
118
119    /// Reads a global index from Wasm code and validates that it is a valid
120    /// index for a given globals vector.
121    pub fn decode_and_validate<T>(
122        wasm: &mut WasmDecoder,
123        c_globals: &IdxVec<GlobalIdx, T>,
124    ) -> Result<Self, ValidationError> {
125        let index = wasm.decode_var_u32()?;
126        Self::validate(index, c_globals)
127    }
128}
129
130impl ElemIdx {
131    /// Validates that a given index is a valid element index.
132    ///
133    /// On success a new [`ElemIdx`] is returned, otherwise a
134    /// [`ValidationError`] is returned.
135    pub fn validate<T>(index: u32, c_elems: &IdxVec<ElemIdx, T>) -> Result<Self, ValidationError> {
136        c_elems
137            .validate_index(index)
138            .ok_or(ValidationError::InvalidElemIdx(index))
139    }
140
141    /// Reads an element index from Wasm code and validates that it is a valid
142    /// index for a given elements vector.
143    pub fn decode_and_validate<T>(
144        wasm: &mut WasmDecoder,
145        c_elems: &IdxVec<ElemIdx, T>,
146    ) -> Result<Self, ValidationError> {
147        let index = wasm.decode_var_u32()?;
148        Self::validate(index, c_elems)
149    }
150}
151
152impl DataIdx {
153    /// Validates that a given index is a valid data index.
154    ///
155    /// On success a new [`DataIdx`] is returned, otherwise a
156    /// [`ValidationError`] is returned.
157    pub fn validate(index: u32, data_count: u32) -> Result<Self, ValidationError> {
158        (index < data_count)
159            .then_some(<Self as Idx>::new(index))
160            .ok_or(ValidationError::InvalidDataIdx(index))
161    }
162
163    /// Reads a data index from Wasm code and validates that it is a valid
164    /// by comparing it to the total number of data segments.
165    pub fn decode_and_validate(
166        wasm: &mut WasmDecoder,
167        data_count: u32,
168    ) -> Result<Self, ValidationError> {
169        let index = wasm.decode_var_u32()?;
170        Self::validate(index, data_count)
171    }
172}
173
174impl LocalIdx {
175    /// Reads a local index from Wasm code and validates that it is valid for a
176    /// given slice of locals.
177    pub fn decode_and_validate(
178        wasm: &mut WasmDecoder,
179        locals_of_current_function: &[ValType],
180    ) -> Result<Self, ValidationError> {
181        let index = wasm.decode_var_u32()?;
182        let index_as_usize = usize::try_from(index).expect("architecture to be at least 32 bits");
183
184        match locals_of_current_function.get(index_as_usize) {
185            Some(_local) => Ok(Self(index)),
186            None => Err(ValidationError::InvalidLocalIdx(index)),
187        }
188    }
189}