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    WriteOnImmutableGlobal,
13    GlobalTypeMismatch,
14    /// A host function returned the [`HaltExecutionError`](crate::HaltExecutionError), which caused execution to be halted.
15    HostFunctionHaltedExecution,
16    // An access to a table element was out of bounds
17    TableAccessOutOfBounds,
18    UnknownExport,
19    TableTypeMismatch,
20
21    // Are all of these instantiation variants? Add a new `InstantiationError` enum?
22    InvalidImportType,
23    /// It was attempted to register a symbol under a name for which a symbol already exists.
24    RegistrySymbolAlreadyExists,
25    MoreThanOneMemory,
26    /// Fueled execution that is not resumable has ran out of fuel.
27    OutOfFuel,
28    /// The number of module exports did not match the number of extern values
29    /// provided for instantiation.
30    ExternValsLenMismatch,
31    /// Happens when a definition would cause an extern to be defined with a
32    /// module name and name for which an extern already exists.
33    DuplicateExternDefinition,
34    /// A function was invoked with incorrect parameters or return types.
35    FunctionInvocationSignatureMismatch,
36}
37
38impl Display for RuntimeError {
39    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
40        match self {
41            RuntimeError::Trap(trap_error) => write!(f, "Execution trapped: {trap_error}"),
42            RuntimeError::FunctionNotFound => f.write_str("Function not found"),
43            RuntimeError::ModuleNotFound => f.write_str("No such module exists"),
44            RuntimeError::ResumableNotFound => f.write_str("No such resumable exists"),
45            RuntimeError::StackExhaustion => {
46                f.write_str("either the call stack or the value stack overflowed")
47            }
48            RuntimeError::HostFunctionSignatureMismatch => {
49                f.write_str("host function call did not respect its type signature")
50            }
51            RuntimeError::HostFunctionHaltedExecution => {
52                f.write_str("A host function requested execution to be halted.")
53            }
54            RuntimeError::InvalidImportType => f.write_str("Invalid import type"),
55            RuntimeError::TableAccessOutOfBounds => f.write_str("A table access was out of bounds"),
56            RuntimeError::RegistrySymbolAlreadyExists => f.write_str(
57                "It was attempted to register a symbol under a name for which a symbol already exists.",
58            ),
59            RuntimeError::UnknownExport => {
60                f.write_str("An unknown export was referenced by its name.")
61            }
62            RuntimeError::TableTypeMismatch => {
63                f.write_str("An alloc/write operation failed on a table due to a type mismatch.")
64            }
65            RuntimeError::MoreThanOneMemory => {
66                f.write_str("As of not only one memory is allowed per module.")
67            }
68
69            RuntimeError::WriteOnImmutableGlobal => f.write_str(
70                "A write operation on a global failed due to the global being immutable",
71            ),
72            RuntimeError::GlobalTypeMismatch => {
73                f.write_str("An alloc/write operation on a global failed due to a type mismatch")
74            }
75            RuntimeError::OutOfFuel => {
76                f.write_str("Fueled execution that is not resumable has ran out of fuel")
77            }
78            RuntimeError::ExternValsLenMismatch => {
79                f.write_str("The number of module exports did not match the number of extern values provided for instantiation.")
80            }
81            RuntimeError::DuplicateExternDefinition => {
82                f.write_str("Linking failed because of a duplicate definition of some extern value")
83            }
84            RuntimeError::FunctionInvocationSignatureMismatch => {
85                f.write_str("A function was invoked with incorrect parameters or return types")
86            }
87        }
88    }
89}
90
91impl core::error::Error for RuntimeError {}
92
93#[derive(Debug, PartialEq, Eq, Clone)]
94pub enum TrapError {
95    DivideBy0,
96    UnrepresentableResult,
97    // https://github.com/wasmi-labs/wasmi/blob/37d1449524a322817c55026eb21eb97dd693b9ce/crates/core/src/trap.rs#L265C5-L265C27
98    BadConversionToInteger,
99
100    /// An access to a memory or data was out of bounds.
101    ///
102    /// Note: As of now, there is no way to distinguish between both of these. The reference
103    /// interpreter and Wast testsuite messages call this error "memory access out of bounds".
104    MemoryOrDataAccessOutOfBounds,
105    /// An access to a table or an element was out of bounds.
106    ///
107    /// Note: As of now, there is no way to distinguish between both of these. The reference
108    /// interpreter and Wast testsuite messages call this error "table access out of bounds".
109    TableOrElementAccessOutOfBounds,
110    UninitializedElement,
111    SignatureMismatch,
112    IndirectCallNullFuncRef,
113    TableAccessOutOfBounds,
114    ReachedUnreachable,
115}
116
117impl Display for TrapError {
118    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
119        match self {
120            TrapError::DivideBy0 => f.write_str("Divide by zero is not permitted"),
121            TrapError::UnrepresentableResult => f.write_str("Result is unrepresentable"),
122            TrapError::BadConversionToInteger => f.write_str("Bad conversion to integer"),
123            TrapError::MemoryOrDataAccessOutOfBounds => {
124                f.write_str("Memory or data access out of bounds")
125            }
126            TrapError::TableOrElementAccessOutOfBounds => {
127                f.write_str("Table or element access out of bounds")
128            }
129            TrapError::UninitializedElement => f.write_str("Uninitialized element"),
130            TrapError::SignatureMismatch => f.write_str("Indirect call signature mismatch"),
131            TrapError::IndirectCallNullFuncRef => {
132                f.write_str("Indirect call targeted null reference")
133            }
134            TrapError::TableAccessOutOfBounds => {
135                f.write_str("Indirect call: table index out of bounds")
136            }
137            TrapError::ReachedUnreachable => f.write_str("An unreachable statement was reached"),
138        }
139    }
140}
141
142impl core::error::Error for TrapError {}
143
144impl From<TrapError> for RuntimeError {
145    fn from(value: TrapError) -> Self {
146        Self::Trap(value)
147    }
148}