1use core::fmt::{Display, Formatter};
2
3use crate::{
4 core::structure::{modules::indices::FuncIdx, types::ValType},
5 validation::validation_stack::ValidationStackEntry,
6 DecodingError, RefType,
7};
8
9#[derive(Debug, PartialEq, Eq, Clone)]
10pub enum ValidationError {
11 Decoding(DecodingError),
12 InvalidTypeIdx(u32),
14 InvalidFuncIdx(u32),
16 InvalidTableIdx(u32),
18 InvalidMemIdx(u32),
20 InvalidGlobalIdx(u32),
22 InvalidElemIdx(u32),
24 InvalidDataIdx(u32),
26 InvalidLocalIdx(u32),
28 InvalidLabelIdx(u32),
30 InvalidLaneIdx(u8),
32
33 ExprMissingEnd,
34 InvalidInstr(u8),
35 InvalidMultiByteInstr(u8, u32),
36 EndInvalidValueStack,
37 InvalidValidationStackValType(Option<ValType>),
38 InvalidValidationStackType(ValidationStackEntry),
39 ExpectedAnOperand,
40 MutationOfConstGlobal,
42 ErroneousAlignment {
44 alignment: u32,
45 minimum_required_alignment: u32,
46 },
47 ValidationCtrlStackEmpty,
50 ElseWithoutMatchingIf,
52 IfWithoutMatchingElse,
54 MismatchedRefTypesDuringTableInit {
56 table_ty: RefType,
57 elem_ty: RefType,
58 },
59 MismatchedRefTypesDuringTableCopy {
61 source_table_ty: RefType,
62 destination_table_ty: RefType,
63 },
64 MismatchedRefTypesOnValidationStack {
66 expected: RefType,
67 actual: RefType,
68 },
69 IndirectCallToNonFuncRefTable(RefType),
71 ExpectedReferenceTypeOnStack(ValType),
73 ReferencingAnUnreferencedFunction(FuncIdx),
75 InvalidSelectTypeVectorLength(usize),
77 DuplicateExportName,
79 UnsupportedMultipleMemoriesProposal,
81 CodeExprHasTrailingInstructions,
83 FunctionAndCodeSectionsHaveDifferentLengths,
85 DataCountAndDataSectionsLengthAreDifferent,
87 InvalidImportType,
88 InvalidStartFunctionSignature,
90 ActiveElementSegmentTypeMismatch,
92 MissingDataCountSection,
95 InvalidDataSegmentMode(u32),
98 InvalidElementMode(u32),
101 TooManyFunctions,
104 TooManyTables,
107 TooManyMemories,
110 TooManyGlobals,
113 LimitsMinLargerThanMax {
115 min: u32,
116 max: u32,
117 },
118 LimitsNotWithinRange(u32),
120 MutGlobalInConstGlobalGet,
122}
123
124impl core::error::Error for ValidationError {}
125
126impl Display for ValidationError {
127 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
128 match self {
129 ValidationError::Decoding(err) => write!(f, "Decoding failed: {err}"),
130
131 ValidationError::InvalidTypeIdx(idx) => write!(f, "The type index {idx} is invalid"),
132 ValidationError::InvalidFuncIdx(idx) => write!(f, "The function index {idx} is invalid"),
133 ValidationError::InvalidTableIdx(idx) => write!(f, "The table index {idx} is invalid"),
134 ValidationError::InvalidMemIdx(idx) => write!(f, "The memory index {idx} is invalid"),
135 ValidationError::InvalidGlobalIdx(idx) => write!(f, "The global index {idx} is invalid"),
136 ValidationError::InvalidElemIdx(idx) => write!(f, "The element segment index {idx} is invalid"),
137 ValidationError::InvalidDataIdx(idx) => write!(f, "The data segment index {idx} is invalid"),
138 ValidationError::InvalidLocalIdx(idx) => write!(f, "The local index {idx} is invalid"),
139 ValidationError::InvalidLabelIdx(idx) => write!(f, "The label index {idx} is invalid"),
140 ValidationError::InvalidLaneIdx(idx) => write!(f, "The lane index {idx} is invalid"),
141
142 ValidationError::ExprMissingEnd => write!(f, "An expr type is missing an end byte"),
143 ValidationError::InvalidInstr(byte) => write!(f, "The instruction {byte:#x} is invalid"),
144 ValidationError::InvalidMultiByteInstr(first_byte, second_instr) => write!(f, "The multi-byte instruction {first_byte:#x} {second_instr} is invalid"),
145 ValidationError::ActiveElementSegmentTypeMismatch => write!(f, "an element segment's type and its table's type are different"),
146 ValidationError::EndInvalidValueStack => write!(f, "Different value stack types were expected at the end of a block/function"),
147 ValidationError::InvalidValidationStackValType(ty) => write!(f, "An unexpected type `{ty:?}` was found on the stack when trying to pop another"),
148 ValidationError::InvalidValidationStackType(ty) => write!(f, "An unexpected type `{ty:?}` was found on the stack"),
149 ValidationError::ExpectedAnOperand => write!(f, "Expected a value type operand on the stack"),
150 ValidationError::MutationOfConstGlobal => write!(f, "An attempt has been made to mutate a const global"),
151 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}"),
152 ValidationError::ValidationCtrlStackEmpty => write!(f, "Failed to retrieve last ctrl block because validation ctrl stack is empty"),
153 ValidationError::ElseWithoutMatchingIf => write!(f, "Found `else` without a previous matching `if` instruction"),
154 ValidationError::IfWithoutMatchingElse => write!(f, "Found `end` without a previous matching `else` to an `if` instruction"),
155 ValidationError::MismatchedRefTypesDuringTableInit { table_ty, elem_ty } => write!(f, "Mismatch of table type `{table_ty:?}` and element segment type `{elem_ty:?}` for `table.init` instruction"),
156 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"),
157 ValidationError::MismatchedRefTypesOnValidationStack { expected, actual } => write!(f, "Mismatch of reference types on the value stack: Expected `{expected:?}` but got `{actual:?}`"),
158 ValidationError::IndirectCallToNonFuncRefTable(table_ty) => write!(f, "An indirect call to a table which does not store function references but instead `{table_ty:?}` was made"),
159 ValidationError::ExpectedReferenceTypeOnStack(found_valtype) => write!(f, "Expected a reference type but instead found a `{found_valtype:?}` on the stack"),
160 ValidationError::ReferencingAnUnreferencedFunction(func_idx) => write!(f, "Referenced a function with index {func_idx} that was not referenced in prior validation"),
161 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"),
162 ValidationError::DuplicateExportName => write!(f,"Multiple exports share the same name"),
163 ValidationError::UnsupportedMultipleMemoriesProposal => write!(f,"A memory index other than 1 was used, but the proposal for multiple memories is not yet supported"),
164 ValidationError::CodeExprHasTrailingInstructions => write!(f,"A code expression has invalid trailing instructions following its `end` instruction"),
165 ValidationError::FunctionAndCodeSectionsHaveDifferentLengths => write!(f,"The function and code sections have different lengths"),
166 ValidationError::DataCountAndDataSectionsLengthAreDifferent => write!(f,"The data count section specifies a different length than there are data segments in the data section"),
167 ValidationError::InvalidImportType => f.write_str("Invalid import type"),
168 ValidationError::InvalidStartFunctionSignature => write!(f,"The start function has parameters or return types which it is not allowed to have"),
169 ValidationError::MissingDataCountSection => f.write_str("Some instructions could not be validated because the data count section is missing"),
170 ValidationError::InvalidDataSegmentMode(mode) => write!(f, "The mode of a data segment was invalid (only 0..=2 is allowed): {mode}"),
171 ValidationError::InvalidElementMode(mode) => write!(f, "The mode of an element was invalid (only 0..=7 is allowed): {mode}"),
172 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"),
173 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"),
174 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"),
175 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"),
176 ValidationError::LimitsMinLargerThanMax { min, max } => write!(f, "Limits are invalid because min={min} is larger than max={max}"),
177 ValidationError::LimitsNotWithinRange(range) => write!(f, "The min or max field of a limits type is not within the expected range of {range}"),
178 ValidationError::MutGlobalInConstGlobalGet => f.write_str("A mutable global was referenced in some global.get instruction in a constant expression"),
179 }
180 }
181}
182
183impl ValidationError {
184 pub fn to_message(&self) -> &'static str {
186 todo!("convert validation error to testsuite message");
187 }
188}
189
190impl From<DecodingError> for ValidationError {
191 fn from(error: DecodingError) -> Self {
192 Self::Decoding(error)
193 }
194}
195
196#[cfg(test)]
197mod test {
198 use alloc::string::ToString;
199
200 use crate::core::decoding::error::DecodingError;
201
202 #[test]
203 fn fmt_invalid_magic() {
204 assert!(DecodingError::InvalidMagic
205 .to_string()
206 .contains("magic number"));
207 }
208
209 #[test]
210 fn fmt_invalid_version() {
211 assert!(DecodingError::InvalidBinaryFormatVersion
212 .to_string()
213 .contains("version"));
214 }
215}