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