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