wasmi/engine/limits/
stack.rs

1use crate::core::UntypedVal;
2use core::{
3    fmt::{self, Display},
4    mem::size_of,
5};
6
7/// Default value for initial value stack height in bytes.
8const DEFAULT_MIN_VALUE_STACK_HEIGHT: usize = 1024;
9
10/// Default value for maximum value stack height in bytes.
11const DEFAULT_MAX_VALUE_STACK_HEIGHT: usize = 1024 * DEFAULT_MIN_VALUE_STACK_HEIGHT;
12
13/// Default value for maximum recursion depth.
14const DEFAULT_MAX_RECURSION_DEPTH: usize = 1024;
15
16/// The configured limits of the Wasm stack.
17#[derive(Debug, Copy, Clone)]
18pub struct StackLimits {
19    /// The initial value stack height that the Wasm stack prepares.
20    pub initial_value_stack_height: usize,
21    /// The maximum value stack height in use that the Wasm stack allows.
22    pub maximum_value_stack_height: usize,
23    /// The maximum number of nested calls that the Wasm stack allows.
24    pub maximum_recursion_depth: usize,
25}
26
27/// An error that may occur when configuring [`StackLimits`].
28#[derive(Debug)]
29pub enum LimitsError {
30    /// The initial value stack height exceeds the maximum value stack height.
31    InitialValueStackExceedsMaximum,
32}
33
34impl Display for LimitsError {
35    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36        match self {
37            LimitsError::InitialValueStackExceedsMaximum => {
38                write!(f, "initial value stack height exceeds maximum stack height")
39            }
40        }
41    }
42}
43
44impl StackLimits {
45    /// Creates a new [`StackLimits`] configuration.
46    ///
47    /// # Errors
48    ///
49    /// If the `initial_value_stack_height` exceeds `maximum_value_stack_height`.
50    pub fn new(
51        initial_value_stack_height: usize,
52        maximum_value_stack_height: usize,
53        maximum_recursion_depth: usize,
54    ) -> Result<Self, LimitsError> {
55        if initial_value_stack_height > maximum_value_stack_height {
56            return Err(LimitsError::InitialValueStackExceedsMaximum);
57        }
58        Ok(Self {
59            initial_value_stack_height,
60            maximum_value_stack_height,
61            maximum_recursion_depth,
62        })
63    }
64}
65
66impl Default for StackLimits {
67    fn default() -> Self {
68        let register_len = size_of::<UntypedVal>();
69        let initial_value_stack_height = DEFAULT_MIN_VALUE_STACK_HEIGHT / register_len;
70        let maximum_value_stack_height = DEFAULT_MAX_VALUE_STACK_HEIGHT / register_len;
71        Self {
72            initial_value_stack_height,
73            maximum_value_stack_height,
74            maximum_recursion_depth: DEFAULT_MAX_RECURSION_DEPTH,
75        }
76    }
77}