1use crate::validation_stack::ValidationStackEntry;
2use crate::RefType;
3use core::fmt::{Display, Formatter};
4use core::str::Utf8Error;
5
6use super::indices::FuncIdx;
7use crate::core::reader::section_header::SectionTy;
8use crate::core::reader::types::ValType;
9
10#[derive(Debug, PartialEq, Eq, Clone)]
11pub enum ValidationError {
12 InvalidMagic,
14 InvalidBinaryFormatVersion,
16 Eof,
18
19 MalformedUtf8(Utf8Error),
21 MalformedSectionTypeDiscriminator(u8),
23 MalformedNumTypeDiscriminator(u8),
25 MalformedVecTypeDiscriminator(u8),
27 MalformedFuncTypeDiscriminator(u8),
29 MalformedRefTypeDiscriminator(u8),
31 MalformedValType,
33 MalformedExportDescDiscriminator(u8),
35 MalformedImportDescDiscriminator(u8),
37 MalformedLimitsDiscriminator(u8),
39 MalformedLimitsMinLargerThanMax {
41 min: u32,
42 max: u32,
43 },
44 MalformedMutDiscriminator(u8),
46 MalformedBlockTypeTypeIdx(i64),
48 MalformedVariableLengthInteger,
50 MalformedElemKindDiscriminator(u8),
52
53 InvalidTypeIdx(u32),
55 InvalidFuncIdx(u32),
57 InvalidTableIdx(u32),
59 InvalidMemIdx(u32),
61 InvalidGlobalIdx(u32),
63 InvalidElemIdx(u32),
65 InvalidDataIdx(u32),
67 InvalidLocalIdx(u32),
69 InvalidLabelIdx(u32),
71 InvalidLaneIdx(u8),
73
74 SectionOutOfOrder(SectionTy),
76 InvalidCustomSectionLength,
78 ExprMissingEnd,
79 InvalidInstr(u8),
80 InvalidMultiByteInstr(u8, u32),
81 EndInvalidValueStack,
82 InvalidValidationStackValType(Option<ValType>),
83 InvalidValidationStackType(ValidationStackEntry),
84 ExpectedAnOperand,
85 MemoryTooLarge,
87 MutationOfConstGlobal,
89 ErroneousAlignment {
91 alignment: u32,
92 minimum_required_alignment: u32,
93 },
94 ValidationCtrlStackEmpty,
97 ElseWithoutMatchingIf,
99 IfWithoutMatchingElse,
101 MismatchedRefTypesDuringTableInit {
103 table_ty: RefType,
104 elem_ty: RefType,
105 },
106 MismatchedRefTypesDuringTableCopy {
108 source_table_ty: RefType,
109 destination_table_ty: RefType,
110 },
111 MismatchedRefTypesOnValidationStack {
113 expected: RefType,
114 actual: RefType,
115 },
116 IndirectCallToNonFuncRefTable(RefType),
118 ExpectedReferenceTypeOnStack(ValType),
120 ReferencingAnUnreferencedFunction(FuncIdx),
122 InvalidSelectTypeVectorLength(usize),
124 TooManyLocals(u64),
126 DuplicateExportName,
128 UnsupportedMultipleMemoriesProposal,
130 CodeExprHasTrailingInstructions,
132 FunctionAndCodeSectionsHaveDifferentLengths,
134 DataCountAndDataSectionsLengthAreDifferent,
136 InvalidImportType,
137 InvalidStartFunctionSignature,
139 ActiveElementSegmentTypeMismatch,
141 I33IsNegative,
145 MissingDataCountSection,
148 InvalidDataSegmentMode(u32),
151 InvalidElementMode(u32),
154 TooManyFunctions,
157 TooManyTables,
160 TooManyMemories,
163 TooManyGlobals,
166}
167
168impl core::error::Error for ValidationError {}
169
170impl Display for ValidationError {
171 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
172 match self {
173 ValidationError::InvalidMagic => write!(f, "The magic number is invalid"),
174 ValidationError::InvalidBinaryFormatVersion => write!(f, "The Wasm binary format version is invalid"),
175 ValidationError::Eof => write!(f, "The end of the Wasm bytecode was reached unexpectedly"),
176
177 ValidationError::MalformedUtf8(utf8_error) => write!(f, "Failed to parse a UTF-8 string: {utf8_error}"),
178 ValidationError::MalformedSectionTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a section type discriminator"),
179 ValidationError::MalformedNumTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a number type discriminator"),
180 ValidationError::MalformedVecTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a vector type discriminator"),
181 ValidationError::MalformedFuncTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a function type discriminator"),
182 ValidationError::MalformedRefTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a reference type discriminator"),
183 ValidationError::MalformedValType => write!(f, "Failed to read a value type because it is neither a number, reference or vector type"),
184 ValidationError::MalformedExportDescDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as an export description discriminator"),
185 ValidationError::MalformedImportDescDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as an import description discriminator"),
186 ValidationError::MalformedLimitsDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a limits type discriminator"),
187 ValidationError::MalformedLimitsMinLargerThanMax { min, max } => write!(f, "Limits are malformed because min={min} is larger than max={max}"),
188 ValidationError::MalformedMutDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a mute type discriminator"),
189 ValidationError::MalformedBlockTypeTypeIdx(idx) => write!(f, "The type index {idx} which is encoded as a singed 33-bit integer inside a block type is malformed"),
190 ValidationError::MalformedVariableLengthInteger => write!(f, "Reading a variable-length integer overflowed"),
191 ValidationError::MalformedElemKindDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as an element kind discriminator"),
192
193 ValidationError::InvalidTypeIdx(idx) => write!(f, "The type index {idx} is invalid"),
194 ValidationError::InvalidFuncIdx(idx) => write!(f, "The function index {idx} is invalid"),
195 ValidationError::InvalidTableIdx(idx) => write!(f, "The table index {idx} is invalid"),
196 ValidationError::InvalidMemIdx(idx) => write!(f, "The memory index {idx} is invalid"),
197 ValidationError::InvalidGlobalIdx(idx) => write!(f, "The global index {idx} is invalid"),
198 ValidationError::InvalidElemIdx(idx) => write!(f, "The element segment index {idx} is invalid"),
199 ValidationError::InvalidDataIdx(idx) => write!(f, "The data segment index {idx} is invalid"),
200 ValidationError::InvalidLocalIdx(idx) => write!(f, "The local index {idx} is invalid"),
201 ValidationError::InvalidLabelIdx(idx) => write!(f, "The label index {idx} is invalid"),
202 ValidationError::InvalidLaneIdx(idx) => write!(f, "The lane index {idx} is invalid"),
203
204 ValidationError::SectionOutOfOrder(ty) => write!(f, "A section of type `{ty:?}` is defined out of order"),
205 ValidationError::InvalidCustomSectionLength => write!(f, "A custom section contains more bytes than its section header specifies"),
206 ValidationError::ExprMissingEnd => write!(f, "An expr type is missing an end byte"),
207 ValidationError::InvalidInstr(byte) => write!(f, "The instruction opcode {byte:#x} is invalid"),
208 ValidationError::InvalidMultiByteInstr(first_byte, second_instr) => write!(f, "The multi-byte instruction opcode {first_byte:#x} {second_instr} is invalid"),
209 ValidationError::ActiveElementSegmentTypeMismatch => write!(f, "an element segment's type and its table's type are different"),
210 ValidationError::EndInvalidValueStack => write!(f, "Different value stack types were expected at the end of a block/function"),
211 ValidationError::InvalidValidationStackValType(ty) => write!(f, "An unexpected type `{ty:?}` was found on the stack when trying to pop another"),
212 ValidationError::InvalidValidationStackType(ty) => write!(f, "An unexpected type `{ty:?}` was found on the stack"),
213 ValidationError::ExpectedAnOperand => write!(f, "Expected a value type operand on the stack"),
214 ValidationError::MemoryTooLarge => write!(f, "The size specified by a memory type exceeds the maximum size"),
215 ValidationError::MutationOfConstGlobal => write!(f, "An attempt has been made to mutate a const global"),
216 ValidationError::ErroneousAlignment {alignment , minimum_required_alignment} => write!(f, "The alignment 2^{alignment} is not less or equal to the required alignment 2^{minimum_required_alignment}"),
217 ValidationError::ValidationCtrlStackEmpty => write!(f, "Failed to retrieve last ctrl block because validation ctrl stack is empty"),
218 ValidationError::ElseWithoutMatchingIf => write!(f, "Found `else` without a previous matching `if` instruction"),
219 ValidationError::IfWithoutMatchingElse => write!(f, "Found `end` without a previous matching `else` to an `if` instruction"),
220 ValidationError::MismatchedRefTypesDuringTableInit { table_ty, elem_ty } => write!(f, "Mismatch of table type `{table_ty:?}` and element segment type `{elem_ty:?}` for `table.init` instruction"),
221 ValidationError::MismatchedRefTypesDuringTableCopy { source_table_ty, destination_table_ty } => write!(f, "Mismatch of source table type `{source_table_ty:?}` and destination table type `{destination_table_ty:?}` for `table.copy` instruction"),
222 ValidationError::MismatchedRefTypesOnValidationStack { expected, actual } => write!(f, "Mismatch of reference types on the value stack: Expected `{expected:?}` but got `{actual:?}`"),
223 ValidationError::IndirectCallToNonFuncRefTable(table_ty) => write!(f, "An indirect call to a table which does not store function references but instead `{table_ty:?}` was made"),
224 ValidationError::ExpectedReferenceTypeOnStack(found_valtype) => write!(f, "Expected a reference type but instead found a `{found_valtype:?}` on the stack"),
225 ValidationError::ReferencingAnUnreferencedFunction(func_idx) => write!(f, "Referenced a function with index {func_idx} that was not referenced in prior validation"),
226 ValidationError::InvalidSelectTypeVectorLength(len) => write!(f, "The type vector of a `select` instruction must be of length 1 as of now but it is of length {len} instead"),
227 ValidationError::TooManyLocals(n) => write!(f,"There are {n} locals and this exceeds the maximum allowed number of 2^32-1"),
228 ValidationError::DuplicateExportName => write!(f,"Multiple exports share the same name"),
229 ValidationError::UnsupportedMultipleMemoriesProposal => write!(f,"A memory index other than 1 was used, but the proposal for multiple memories is not yet supported"),
230 ValidationError::CodeExprHasTrailingInstructions => write!(f,"A code expression has invalid trailing instructions following its `end` instruction"),
231 ValidationError::FunctionAndCodeSectionsHaveDifferentLengths => write!(f,"The function and code sections have different lengths"),
232 ValidationError::DataCountAndDataSectionsLengthAreDifferent => write!(f,"The data count section specifies a different length than there are data segments in the data section"),
233 ValidationError::InvalidImportType => f.write_str("Invalid import type"),
234 ValidationError::InvalidStartFunctionSignature => write!(f,"The start function has parameters or return types which it is not allowed to have"),
235 ValidationError::I33IsNegative => f.write_str("An i33 type is negative which is not allowed"),
236 ValidationError::MissingDataCountSection => f.write_str("Some instructions could not be validated because the data count section is missing"),
237 ValidationError::InvalidDataSegmentMode(mode) => write!(f, "The mode of a data segment was invalid (only 0..=2 is allowed): {mode}"),
238 ValidationError::InvalidElementMode(mode) => write!(f, "The mode of an element was invalid (only 0..=7 is allowed): {mode}"),
239 ValidationError::TooManyFunctions => f.write_str("The module contains too many functions. The maximum number of functions (either imported or locally-defined) is 2^32 - 1"),
240 ValidationError::TooManyTables => f.write_str("The module contains too many tables. The maximum number of tables (either imported or locally-defined) is 2^32 - 1"),
241 ValidationError::TooManyMemories => f.write_str("The module contains too many memories. The maximum number of memories (either imported or locally-defined) is 2^32 - 1"),
242 ValidationError::TooManyGlobals => f.write_str("The module contains too many globals. The maximum number of globals (either imported or locally-defined) is 2^32 - 1"),
243 }
244 }
245}
246
247impl ValidationError {
248 pub fn to_message(&self) -> &'static str {
250 todo!("convert validation error to testsuite message");
251 }
252}
253
254#[cfg(test)]
255mod test {
256 use alloc::string::ToString;
257
258 use crate::ValidationError;
259
260 #[test]
261 fn fmt_invalid_magic() {
262 assert!(ValidationError::InvalidMagic
263 .to_string()
264 .contains("magic number"));
265 }
266
267 #[test]
268 fn fmt_invalid_version() {
269 assert!(ValidationError::InvalidBinaryFormatVersion
270 .to_string()
271 .contains("version"));
272 }
273}