1use alloc::format;
2use alloc::string::{String, ToString};
3
4use crate::core::indices::GlobalIdx;
5use crate::validation_stack::ValidationStackEntry;
6use crate::RefType;
7use core::fmt::{Display, Formatter};
8use core::str::Utf8Error;
9
10use crate::core::reader::section_header::SectionTy;
11use crate::core::reader::types::ValType;
12
13use super::indices::{DataIdx, ElemIdx, FuncIdx, MemIdx, TableIdx, TypeIdx};
14
15#[derive(Debug, PartialEq, Eq, Clone)]
16pub enum RuntimeError {
17 DivideBy0,
18 UnrepresentableResult,
19 FunctionNotFound,
20 BadConversionToInteger,
22 MemoryAccessOutOfBounds,
23 TableAccessOutOfBounds,
24 ElementAccessOutOfBounds,
25 UninitializedElement,
26 SignatureMismatch,
27 ExpectedAValueOnTheStack,
28 ModuleNotFound,
29 UnmetImport,
30 UndefinedTableIndex,
31 ReachedUnreachable,
33 StackExhaustion,
34 HostFunctionSignatureMismatch,
35}
36
37#[derive(Debug, PartialEq, Eq, Clone)]
38pub enum Proposal {
39 Memory64,
40 MultipleMemories,
41 Threads,
42}
43
44#[derive(Debug, PartialEq, Eq, Clone)]
45pub enum StoreInstantiationError {
46 ActiveDataWriteOutOfBounds,
47 I64ValueOutOfReach(String),
48 MissingValueOnTheStack,
49 TooManyMemories(usize),
50}
51
52#[derive(Debug, PartialEq, Eq, Clone)]
53pub enum LinkerError {
54 UnmetImport,
55}
56
57#[derive(Debug, PartialEq, Eq, Clone)]
58pub enum Error {
59 InvalidMagic,
61 InvalidVersion,
62 MalformedUtf8String(Utf8Error),
63 Eof,
64 InvalidSection(SectionTy, String),
65 InvalidSectionType(u8),
66 SectionOutOfOrder(SectionTy),
67 InvalidNumType,
68 InvalidVecType,
69 InvalidFuncType,
70 InvalidFuncTypeIdx,
71 InvalidRefType,
72 InvalidValType,
73 InvalidExportDesc(u8),
74 InvalidImportDesc(u8),
75 ExprMissingEnd,
76 InvalidInstr(u8),
77 InvalidMultiByteInstr(u8, u32),
78 EndInvalidValueStack,
79 InvalidLocalIdx,
80 InvalidValidationStackValType(Option<ValType>),
81 InvalidValidationStackType(ValidationStackEntry),
82 ExpectedAnOperand,
83 InvalidLimitsType(u8),
84 InvalidMutType(u8),
85 MoreThanOneMemory,
86 InvalidLimit,
87 MemSizeTooBig,
88 InvalidGlobalIdx(GlobalIdx),
89 GlobalIsConst,
90 RuntimeError(RuntimeError),
91 MemoryIsNotDefined(MemIdx),
92 ErroneousAlignment(u32, u32),
94 NoDataSegments,
95 DataSegmentNotFound(DataIdx),
96 InvalidLabelIdx(usize),
97 ValidationCtrlStackEmpty,
98 ElseWithoutMatchingIf,
99 IfWithoutMatchingElse,
100 UnknownTable,
101 TableIsNotDefined(TableIdx),
102 ElementIsNotDefined(ElemIdx),
103 DifferentRefTypes(RefType, RefType),
104 ExpectedARefType(ValType),
105 WrongRefTypeForInteropValue(RefType, RefType),
106 FunctionIsNotDefined(FuncIdx),
107 ReferencingAnUnreferencedFunction(FuncIdx),
108 FunctionTypeIsNotDefined(TypeIdx),
109 StoreInstantiationError(StoreInstantiationError),
110 OnlyFuncRefIsAllowed,
111 TypeUnificationMismatch,
112 InvalidSelectTypeVector,
113 TooManyLocals(usize),
114 UnsupportedProposal(Proposal),
115 Overflow,
116 LinkerError(LinkerError),
117 UnknownFunction,
118 UnknownMemory,
119 UnknownGlobal,
120 UnknownImport, DuplicateExportName,
122 InvalidImportType,
123}
124
125impl Display for Error {
126 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
127 match self {
128 Error::InvalidMagic => {
129 f.write_str("The magic number at the very start of the given WASM file is invalid.")
130 }
131 Error::InvalidVersion => f.write_str("The version in the WASM file header is invalid"),
132 Error::MalformedUtf8String(err) => f.write_fmt(format_args!(
133 "A name could not be parsed as it was invalid UTF8: {err}"
134 )),
135 Error::Eof => f.write_str(
136 "A value was expected in the WASM binary but the end of file was reached instead",
137 ),
138 Error::InvalidSection(section, reason) => f.write_fmt(format_args!(
139 "Section '{section:?}' invalid! Reason: {reason}"
140 )),
141 Error::InvalidSectionType(ty) => f.write_fmt(format_args!(
142 "An invalid section type id was found in a section header: {ty}"
143 )),
144 Error::SectionOutOfOrder(ty) => {
145 f.write_fmt(format_args!("The section {ty:?} is out of order"))
146 }
147 Error::InvalidNumType => {
148 f.write_str("An invalid byte was read where a numtype was expected")
149 }
150 Error::InvalidVecType => {
151 f.write_str("An invalid byte was read where a vectype was expected")
152 }
153 Error::InvalidFuncType => {
154 f.write_str("An invalid byte was read where a functype was expected")
155 }
156 Error::InvalidFuncTypeIdx => {
157 f.write_str("An invalid index to the fuctypes table was read")
158 }
159 Error::InvalidRefType => {
160 f.write_str("An invalid byte was read where a reftype was expected")
161 }
162 Error::InvalidValType => {
163 f.write_str("An invalid byte was read where a valtype was expected")
164 }
165 Error::InvalidExportDesc(byte) => f.write_fmt(format_args!(
166 "An invalid byte `{byte:#x?}` was read where an exportdesc was expected"
167 )),
168 Error::InvalidImportDesc(byte) => f.write_fmt(format_args!(
169 "An invalid byte `{byte:#x?}` was read where an importdesc was expected"
170 )),
171 Error::ExprMissingEnd => f.write_str("An expr is missing an end byte"),
172 Error::InvalidInstr(byte) => f.write_fmt(format_args!(
173 "An invalid instruction opcode was found: `{byte:#x?}`"
174 )),
175 Error::InvalidMultiByteInstr(byte1, byte2) => f.write_fmt(format_args!(
176 "An invalid multi-byte instruction opcode was found: `{byte1:#x?} {byte2:#x?}`"
177 )),
178 Error::EndInvalidValueStack => f.write_str(
179 "Different value stack types were expected at the end of a block/function.",
180 ),
181 Error::InvalidLocalIdx => f.write_str("An invalid localidx was used"),
182 Error::InvalidValidationStackValType(ty) => f.write_fmt(format_args!(
183 "An unexpected type was found on the stack when trying to pop another: `{ty:?}`"
184 )),
185 Error::InvalidValidationStackType(ty) => f.write_fmt(format_args!(
186 "An unexpected type was found on the stack: `{ty:?}`"
187 )),
188 Error::InvalidLimitsType(ty) => {
189 f.write_fmt(format_args!("An invalid limits type was found: {ty:#x?}"))
190 }
191 Error::InvalidMutType(byte) => f.write_fmt(format_args!(
192 "An invalid mut/const byte was found: {byte:#x?}"
193 )),
194 Error::MoreThanOneMemory => {
195 f.write_str("As of not only one memory is allowed per module.")
196 }
197 Error::InvalidLimit => f.write_str("Size minimum must not be greater than maximum"),
198 Error::MemSizeTooBig => f.write_str("Memory size must be at most 65536 pages (4GiB)"),
199 Error::InvalidGlobalIdx(idx) => f.write_fmt(format_args!(
200 "An invalid global index `{idx}` was specified"
201 )),
202 Error::GlobalIsConst => f.write_str("A const global cannot be written to"),
203 Error::RuntimeError(err) => err.fmt(f),
204 Error::ExpectedAnOperand => f.write_str("Expected a ValType"), Error::MemoryIsNotDefined(memidx) => f.write_fmt(format_args!(
206 "C.mems[{memidx}] is NOT defined when it should be"
207 )),
208 Error::ErroneousAlignment(mem_align, minimum_wanted_alignment) => {
209 f.write_fmt(format_args!(
210 "Alignment ({mem_align}) is not less or equal to {minimum_wanted_alignment}"
211 ))
212 }
213 Error::NoDataSegments => f.write_str("Data Count is None"),
214 Error::DataSegmentNotFound(data_idx) => {
215 f.write_fmt(format_args!("Data Segment {data_idx} not found"))
216 }
217 Error::InvalidLabelIdx(label_idx) => {
218 f.write_fmt(format_args!("invalid label index {label_idx}"))
219 }
220 Error::ValidationCtrlStackEmpty => {
221 f.write_str("cannot retrieve last ctrl block, validation ctrl stack is empty")
222 }
223 Error::ElseWithoutMatchingIf => {
224 f.write_str("read 'else' without a previous matching 'if' instruction")
225 }
226 Error::IfWithoutMatchingElse => {
227 f.write_str("read 'end' without matching 'else' instruction to 'if' instruction")
228 }
229 Error::TableIsNotDefined(table_idx) => f.write_fmt(format_args!(
230 "C.tables[{table_idx}] is NOT defined when it should be"
231 )),
232 Error::ElementIsNotDefined(elem_idx) => f.write_fmt(format_args!(
233 "C.elems[{elem_idx}] is NOT defined when it should be"
234 )),
235 Error::DifferentRefTypes(rref1, rref2) => f.write_fmt(format_args!(
236 "RefType {rref1:?} is NOT equal to RefType {rref2:?}"
237 )),
238 Error::ExpectedARefType(found_valtype) => f.write_fmt(format_args!(
239 "Expected a RefType, found a {found_valtype:?} instead"
240 )),
241 Error::WrongRefTypeForInteropValue(ref_given, ref_wanted) => f.write_fmt(format_args!(
242 "Wrong RefType for InteropValue: Given {ref_given:?} - Needed {ref_wanted:?}"
243 )),
244 Error::FunctionIsNotDefined(func_idx) => f.write_fmt(format_args!(
245 "C.functions[{func_idx}] is NOT defined when it should be"
246 )),
247 Error::ReferencingAnUnreferencedFunction(func_idx) => f.write_fmt(format_args!(
248 "Referenced a function ({func_idx}) that was not referenced in validation"
249 )),
250 Error::FunctionTypeIsNotDefined(func_ty_idx) => f.write_fmt(format_args!(
251 "C.fn_types[{func_ty_idx}] is NOT defined when it should be"
252 )),
253 Error::StoreInstantiationError(err) => err.fmt(f),
254 Error::OnlyFuncRefIsAllowed => f.write_str("Only FuncRef is allowed"),
255 Error::TypeUnificationMismatch => {
256 f.write_str("cannot unify types")
257 }
258 Error::InvalidSelectTypeVector => {
259 f.write_str("SELECT T* (0x1C) instruction must have exactly one type in the subsequent type vector")
260 }
261 Error::TooManyLocals(x) => {
262 f.write_fmt(format_args!("Too many locals (more than 2^32-1): {x}"))
263 }
264 Error::UnsupportedProposal(proposal) => {
265 f.write_fmt(format_args!("Unsupported proposal: {proposal:?}"))
266 }
267 Error::Overflow => f.write_str("Overflow"),
268 Error::LinkerError(err) => err.fmt(f),
269
270 Error::UnknownFunction => f.write_str("Unknown function"),
272 Error::UnknownMemory => f.write_str("Unknown memory"),
273 Error::UnknownGlobal => f.write_str("Unknown global"),
274 Error::UnknownTable => f.write_str("Unknown table"),
275 Error::DuplicateExportName => f.write_str("Duplicate export name"),
276 Error::InvalidImportType => f.write_str("Invalid import type"),
277 Error::UnknownImport => f.write_str("Unknown Import"),
279
280 }
281 }
282}
283
284impl Display for RuntimeError {
285 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
286 match self {
287 RuntimeError::DivideBy0 => f.write_str("Divide by zero is not permitted"),
288 RuntimeError::UnrepresentableResult => f.write_str("Result is unrepresentable"),
289 RuntimeError::FunctionNotFound => f.write_str("Function not found"),
290 RuntimeError::BadConversionToInteger => f.write_str("Bad conversion to integer"),
291 RuntimeError::MemoryAccessOutOfBounds => f.write_str("Memory access out of bounds"),
292 RuntimeError::TableAccessOutOfBounds => f.write_str("Table access out of bounds"),
293 RuntimeError::ElementAccessOutOfBounds => f.write_str("Element access out of bounds"),
294 RuntimeError::UninitializedElement => f.write_str("Uninitialized element"),
295 RuntimeError::SignatureMismatch => f.write_str("Indirect call signature mismatch"),
296 RuntimeError::ExpectedAValueOnTheStack => {
297 f.write_str("Expected a value on the stack, but None was found")
298 }
299 RuntimeError::ModuleNotFound => f.write_str("No such module exists"),
300 RuntimeError::UnmetImport => {
301 f.write_str("There is at least one import which has no corresponding export")
302 }
303 RuntimeError::UndefinedTableIndex => {
304 f.write_str("Indirect call: table index out of bounds")
305 }
306 RuntimeError::ReachedUnreachable => {
307 f.write_str("an unreachable statement was reached, triggered a trap")
308 }
309 RuntimeError::StackExhaustion => {
310 f.write_str("either the call stack or the value stack overflowed")
311 }
312 RuntimeError::HostFunctionSignatureMismatch => {
313 f.write_str("host function call did not respect its type signature")
314 }
315 }
316 }
317}
318
319impl Display for StoreInstantiationError {
320 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
321 use StoreInstantiationError::*;
322 match self {
323 ActiveDataWriteOutOfBounds => {
324 f.write_str("Active data writing in memory is out of bounds")
325 }
326 I64ValueOutOfReach(s) => f.write_fmt(format_args!(
327 "I64 value {}is out of reach",
328 if !s.is_empty() {
329 format!("for {s} ")
330 } else {
331 "".to_string()
332 }
333 )),
334 MissingValueOnTheStack => f.write_str(""),
335 TooManyMemories(x) => f.write_fmt(format_args!("Too many memories (overflow): {x}")),
336 }
337 }
338}
339
340impl Display for LinkerError {
341 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
342 use LinkerError::*;
343 match self {
344 UnmetImport => f.write_str("Unmet import"),
345 }
346 }
347}
348
349pub type Result<T> = core::result::Result<T, Error>;
350
351impl From<RuntimeError> for Error {
352 fn from(value: RuntimeError) -> Self {
353 Self::RuntimeError(value)
354 }
355}
356
357impl From<StoreInstantiationError> for Error {
358 fn from(value: StoreInstantiationError) -> Self {
359 Self::StoreInstantiationError(value)
360 }
361}