wasm/execution/
error.rs

1use core::fmt::{Display, Formatter};
2
3#[derive(Debug, PartialEq, Eq, Clone)]
4pub enum RuntimeError {
5    Trap(TrapError),
6
7    ModuleNotFound,
8    FunctionNotFound,
9    ResumableNotFound,
10    StackExhaustion,
11    HostFunctionSignatureMismatch,
12
13    // Are all of these instantiation variants? Add a new `InstantiationError` enum?
14    InvalidImportType,
15    UnknownImport,
16    MoreThanOneMemory,
17    OutOfFuel,
18}
19
20impl Display for RuntimeError {
21    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
22        match self {
23            RuntimeError::Trap(trap_error) => write!(f, "{trap_error}"),
24            RuntimeError::FunctionNotFound => f.write_str("Function not found"),
25            RuntimeError::ModuleNotFound => f.write_str("No such module exists"),
26            RuntimeError::ResumableNotFound => f.write_str("No such resumable exists"),
27            RuntimeError::StackExhaustion => {
28                f.write_str("either the call stack or the value stack overflowed")
29            }
30            RuntimeError::HostFunctionSignatureMismatch => {
31                f.write_str("host function call did not respect its type signature")
32            }
33            RuntimeError::InvalidImportType => f.write_str("Invalid import type"),
34            // TODO: maybe move these to LinkerError also add more info to them (the name's export, function idx, etc)
35            RuntimeError::UnknownImport => f.write_str("Unknown Import"),
36            RuntimeError::MoreThanOneMemory => {
37                f.write_str("As of not only one memory is allowed per module.")
38            }
39            RuntimeError::OutOfFuel => f.write_str("ran out of fuel"),
40        }
41    }
42}
43
44#[derive(Debug, PartialEq, Eq, Clone)]
45pub enum TrapError {
46    DivideBy0,
47    UnrepresentableResult,
48    // https://github.com/wasmi-labs/wasmi/blob/37d1449524a322817c55026eb21eb97dd693b9ce/crates/core/src/trap.rs#L265C5-L265C27
49    BadConversionToInteger,
50
51    /// An access to a memory or data was out of bounds.
52    ///
53    /// Note: As of now, there is no way to distinguish between both of these. The reference
54    /// interpreter and Wast testsuite messages call this error "memory access out of bounds".
55    MemoryOrDataAccessOutOfBounds,
56    /// An access to a table or an element was out of bounds.
57    ///
58    /// Note: As of now, there is no way to distinguish between both of these. The reference
59    /// interpreter and Wast testsuite messages call this error "table access out of bounds".
60    TableOrElementAccessOutOfBounds,
61    UninitializedElement,
62    SignatureMismatch,
63    IndirectCallNullFuncRef,
64    TableAccessOutOfBounds,
65    ReachedUnreachable,
66}
67
68impl Display for TrapError {
69    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
70        match self {
71            TrapError::DivideBy0 => f.write_str("Divide by zero is not permitted"),
72            TrapError::UnrepresentableResult => f.write_str("Result is unrepresentable"),
73            TrapError::BadConversionToInteger => f.write_str("Bad conversion to integer"),
74            TrapError::MemoryOrDataAccessOutOfBounds => {
75                f.write_str("Memory or data access out of bounds")
76            }
77            TrapError::TableOrElementAccessOutOfBounds => {
78                f.write_str("Table or element access out of bounds")
79            }
80            TrapError::UninitializedElement => f.write_str("Uninitialized element"),
81            TrapError::SignatureMismatch => f.write_str("Indirect call signature mismatch"),
82            TrapError::IndirectCallNullFuncRef => {
83                f.write_str("Indirect call targeted null reference")
84            }
85            TrapError::TableAccessOutOfBounds => {
86                f.write_str("Indirect call: table index out of bounds")
87            }
88            TrapError::ReachedUnreachable => {
89                f.write_str("an unreachable statement was reached, triggered a trap")
90            }
91        }
92    }
93}
94
95impl From<TrapError> for RuntimeError {
96    fn from(value: TrapError) -> Self {
97        Self::Trap(value)
98    }
99}