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 DecodingError {
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 { min: u32, max: u32 },
41 MalformedMutDiscriminator(u8),
43 MalformedBlockTypeTypeIdx(i64),
45 MalformedVariableLengthInteger,
47 MalformedElemKindDiscriminator(u8),
49 I33IsNegative,
53 TooManyLocals(u64),
55 MemoryTooLarge,
57}
58
59impl core::error::Error for DecodingError {}
60
61impl Display for DecodingError {
62 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
63 match self {
64 DecodingError::InvalidMagic => write!(f, "The magic number is invalid"),
65 DecodingError::InvalidBinaryFormatVersion => write!(f, "The Wasm binary format version is invalid"),
66 DecodingError::Eof => write!(f, "The end of the Wasm bytecode was reached unexpectedly"),
67 DecodingError::MalformedUtf8(utf8_error) => write!(f, "Failed to parse a UTF-8 string: {utf8_error}"),
68 DecodingError::MalformedSectionTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a section type discriminator"),
69 DecodingError::MalformedNumTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a number type discriminator"),
70 DecodingError::MalformedVecTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a vector type discriminator"),
71 DecodingError::MalformedFuncTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a function type discriminator"),
72 DecodingError::MalformedRefTypeDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a reference type discriminator"),
73 DecodingError::MalformedValType => write!(f, "Failed to read a value type because it is neither a number, reference or vector type"),
74 DecodingError::MalformedExportDescDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as an export description discriminator"),
75 DecodingError::MalformedImportDescDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as an import description discriminator"),
76 DecodingError::MalformedLimitsDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a limits type discriminator"),
77 DecodingError::MalformedLimitsMinLargerThanMax { min, max } => write!(f, "Limits are malformed because min={min} is larger than max={max}"),
78 DecodingError::MalformedMutDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as a mute type discriminator"),
79 DecodingError::MalformedBlockTypeTypeIdx(idx) => write!(f, "The type index {idx} which is encoded as a singed 33-bit integer inside a block type is malformed"),
80 DecodingError::MalformedVariableLengthInteger => write!(f, "Reading a variable-length integer overflowed"),
81 DecodingError::MalformedElemKindDiscriminator(byte) => write!(f, "Failed to parse {byte:#x} as an element kind discriminator"),
82 DecodingError::I33IsNegative => f.write_str("An i33 type is negative which is not allowed"),
83 DecodingError::TooManyLocals(n) => write!(f,"There are {n} locals and this exceeds the maximum allowed number of 2^32-1"),
84 DecodingError::MemoryTooLarge => write!(f, "The size specified by a memory type exceeds the maximum size"),
85 }
86 }
87}
88
89#[derive(Debug, PartialEq, Eq, Clone)]
90pub enum ValidationError {
91 Decoding(DecodingError),
92 InvalidTypeIdx(u32),
94 InvalidFuncIdx(u32),
96 InvalidTableIdx(u32),
98 InvalidMemIdx(u32),
100 InvalidGlobalIdx(u32),
102 InvalidElemIdx(u32),
104 InvalidDataIdx(u32),
106 InvalidLocalIdx(u32),
108 InvalidLabelIdx(u32),
110 InvalidLaneIdx(u8),
112
113 SectionOutOfOrder(SectionTy),
115 InvalidCustomSectionLength,
117 ExprMissingEnd,
118 InvalidInstr(u8),
119 InvalidMultiByteInstr(u8, u32),
120 EndInvalidValueStack,
121 InvalidValidationStackValType(Option<ValType>),
122 InvalidValidationStackType(ValidationStackEntry),
123 ExpectedAnOperand,
124 MutationOfConstGlobal,
126 ErroneousAlignment {
128 alignment: u32,
129 minimum_required_alignment: u32,
130 },
131 ValidationCtrlStackEmpty,
134 ElseWithoutMatchingIf,
136 IfWithoutMatchingElse,
138 MismatchedRefTypesDuringTableInit {
140 table_ty: RefType,
141 elem_ty: RefType,
142 },
143 MismatchedRefTypesDuringTableCopy {
145 source_table_ty: RefType,
146 destination_table_ty: RefType,
147 },
148 MismatchedRefTypesOnValidationStack {
150 expected: RefType,
151 actual: RefType,
152 },
153 IndirectCallToNonFuncRefTable(RefType),
155 ExpectedReferenceTypeOnStack(ValType),
157 ReferencingAnUnreferencedFunction(FuncIdx),
159 InvalidSelectTypeVectorLength(usize),
161 DuplicateExportName,
163 UnsupportedMultipleMemoriesProposal,
165 CodeExprHasTrailingInstructions,
167 FunctionAndCodeSectionsHaveDifferentLengths,
169 DataCountAndDataSectionsLengthAreDifferent,
171 InvalidImportType,
172 InvalidStartFunctionSignature,
174 ActiveElementSegmentTypeMismatch,
176 MissingDataCountSection,
179 InvalidDataSegmentMode(u32),
182 InvalidElementMode(u32),
185 TooManyFunctions,
188 TooManyTables,
191 TooManyMemories,
194 TooManyGlobals,
197}
198
199impl core::error::Error for ValidationError {}
200
201impl Display for ValidationError {
202 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
203 match self {
204 ValidationError::Decoding(err) => write!(f, "Decoding failed: {err}"),
205
206 ValidationError::InvalidTypeIdx(idx) => write!(f, "The type index {idx} is invalid"),
207 ValidationError::InvalidFuncIdx(idx) => write!(f, "The function index {idx} is invalid"),
208 ValidationError::InvalidTableIdx(idx) => write!(f, "The table index {idx} is invalid"),
209 ValidationError::InvalidMemIdx(idx) => write!(f, "The memory index {idx} is invalid"),
210 ValidationError::InvalidGlobalIdx(idx) => write!(f, "The global index {idx} is invalid"),
211 ValidationError::InvalidElemIdx(idx) => write!(f, "The element segment index {idx} is invalid"),
212 ValidationError::InvalidDataIdx(idx) => write!(f, "The data segment index {idx} is invalid"),
213 ValidationError::InvalidLocalIdx(idx) => write!(f, "The local index {idx} is invalid"),
214 ValidationError::InvalidLabelIdx(idx) => write!(f, "The label index {idx} is invalid"),
215 ValidationError::InvalidLaneIdx(idx) => write!(f, "The lane index {idx} is invalid"),
216
217 ValidationError::SectionOutOfOrder(ty) => write!(f, "A section of type `{ty:?}` is defined out of order"),
218 ValidationError::InvalidCustomSectionLength => write!(f, "A custom section contains more bytes than its section header specifies"),
219 ValidationError::ExprMissingEnd => write!(f, "An expr type is missing an end byte"),
220 ValidationError::InvalidInstr(byte) => write!(f, "The instruction opcode {byte:#x} is invalid"),
221 ValidationError::InvalidMultiByteInstr(first_byte, second_instr) => write!(f, "The multi-byte instruction opcode {first_byte:#x} {second_instr} is invalid"),
222 ValidationError::ActiveElementSegmentTypeMismatch => write!(f, "an element segment's type and its table's type are different"),
223 ValidationError::EndInvalidValueStack => write!(f, "Different value stack types were expected at the end of a block/function"),
224 ValidationError::InvalidValidationStackValType(ty) => write!(f, "An unexpected type `{ty:?}` was found on the stack when trying to pop another"),
225 ValidationError::InvalidValidationStackType(ty) => write!(f, "An unexpected type `{ty:?}` was found on the stack"),
226 ValidationError::ExpectedAnOperand => write!(f, "Expected a value type operand on the stack"),
227 ValidationError::MutationOfConstGlobal => write!(f, "An attempt has been made to mutate a const global"),
228 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}"),
229 ValidationError::ValidationCtrlStackEmpty => write!(f, "Failed to retrieve last ctrl block because validation ctrl stack is empty"),
230 ValidationError::ElseWithoutMatchingIf => write!(f, "Found `else` without a previous matching `if` instruction"),
231 ValidationError::IfWithoutMatchingElse => write!(f, "Found `end` without a previous matching `else` to an `if` instruction"),
232 ValidationError::MismatchedRefTypesDuringTableInit { table_ty, elem_ty } => write!(f, "Mismatch of table type `{table_ty:?}` and element segment type `{elem_ty:?}` for `table.init` instruction"),
233 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"),
234 ValidationError::MismatchedRefTypesOnValidationStack { expected, actual } => write!(f, "Mismatch of reference types on the value stack: Expected `{expected:?}` but got `{actual:?}`"),
235 ValidationError::IndirectCallToNonFuncRefTable(table_ty) => write!(f, "An indirect call to a table which does not store function references but instead `{table_ty:?}` was made"),
236 ValidationError::ExpectedReferenceTypeOnStack(found_valtype) => write!(f, "Expected a reference type but instead found a `{found_valtype:?}` on the stack"),
237 ValidationError::ReferencingAnUnreferencedFunction(func_idx) => write!(f, "Referenced a function with index {func_idx} that was not referenced in prior validation"),
238 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"),
239 ValidationError::DuplicateExportName => write!(f,"Multiple exports share the same name"),
240 ValidationError::UnsupportedMultipleMemoriesProposal => write!(f,"A memory index other than 1 was used, but the proposal for multiple memories is not yet supported"),
241 ValidationError::CodeExprHasTrailingInstructions => write!(f,"A code expression has invalid trailing instructions following its `end` instruction"),
242 ValidationError::FunctionAndCodeSectionsHaveDifferentLengths => write!(f,"The function and code sections have different lengths"),
243 ValidationError::DataCountAndDataSectionsLengthAreDifferent => write!(f,"The data count section specifies a different length than there are data segments in the data section"),
244 ValidationError::InvalidImportType => f.write_str("Invalid import type"),
245 ValidationError::InvalidStartFunctionSignature => write!(f,"The start function has parameters or return types which it is not allowed to have"),
246 ValidationError::MissingDataCountSection => f.write_str("Some instructions could not be validated because the data count section is missing"),
247 ValidationError::InvalidDataSegmentMode(mode) => write!(f, "The mode of a data segment was invalid (only 0..=2 is allowed): {mode}"),
248 ValidationError::InvalidElementMode(mode) => write!(f, "The mode of an element was invalid (only 0..=7 is allowed): {mode}"),
249 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"),
250 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"),
251 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"),
252 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"),
253 }
254 }
255}
256
257impl ValidationError {
258 pub fn to_message(&self) -> &'static str {
260 todo!("convert validation error to testsuite message");
261 }
262}
263
264impl From<DecodingError> for ValidationError {
265 fn from(error: DecodingError) -> Self {
266 Self::Decoding(error)
267 }
268}
269
270#[cfg(test)]
271mod test {
272 use alloc::string::ToString;
273
274 use crate::core::error::DecodingError;
275
276 #[test]
277 fn fmt_invalid_magic() {
278 assert!(DecodingError::InvalidMagic
279 .to_string()
280 .contains("magic number"));
281 }
282
283 #[test]
284 fn fmt_invalid_version() {
285 assert!(DecodingError::InvalidBinaryFormatVersion
286 .to_string()
287 .contains("version"));
288 }
289}