From 9cdd72575773bb8eb4608563469d7731ffb78e3b Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 22 Nov 2023 17:36:00 +0100 Subject: [PATCH 1/2] fix: safer stack --- crates/interpreter/src/interpreter/stack.rs | 31 +++++++++++++++++++-- crates/revm/src/inspector/eip3155.rs | 10 +++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index f64b8a0f9f..7b82b5ceed 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -8,9 +8,9 @@ use core::fmt; /// EVM interpreter stack limit. pub const STACK_LIMIT: usize = 1024; -/// EVM stack. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// EVM stack with [STACK_LIMIT] capacity of words. +#[derive(Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct Stack { /// The underlying data of the stack. data: Vec, @@ -64,6 +64,12 @@ impl Stack { &self.data } + /// Consumes the stack and returns the underlying data. + #[inline] + pub fn into_data(self) -> Vec { + self.data + } + /// Removes the topmost element from the stack and returns it, or `StackUnderflow` if it is /// empty. #[inline] @@ -304,6 +310,25 @@ impl Stack { } } +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for Stack { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let mut data = Vec::::deserialize(deserializer)?; + if data.len() > STACK_LIMIT { + return Err(serde::de::Error::custom(format!( + "stack size exceeds limit: {} > {}", + data.len(), + STACK_LIMIT + ))); + } + data.reserve(STACK_LIMIT - data.len()); + Ok(Self { data }) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/crates/revm/src/inspector/eip3155.rs b/crates/revm/src/inspector/eip3155.rs index 6a3bf9a6c5..a10dbf265a 100644 --- a/crates/revm/src/inspector/eip3155.rs +++ b/crates/revm/src/inspector/eip3155.rs @@ -1,6 +1,6 @@ use crate::{ inspectors::GasInspector, - interpreter::{opcode, CallInputs, CreateInputs, Interpreter, InterpreterResult, Stack}, + interpreter::{opcode, CallInputs, CreateInputs, Interpreter, InterpreterResult}, primitives::{db::Database, hex, Address, U256}, EvmContext, Inspector, }; @@ -18,7 +18,7 @@ pub struct TracerEip3155 { #[allow(dead_code)] trace_return_data: bool, - stack: Stack, + stack: Vec, pc: usize, opcode: u8, gas: u64, @@ -33,7 +33,7 @@ impl TracerEip3155 { gas_inspector: GasInspector::default(), trace_mem, trace_return_data, - stack: Stack::new(), + stack: Default::default(), pc: 0, opcode: 0, gas: 0, @@ -52,7 +52,7 @@ impl Inspector for TracerEip3155 { // all other information can be obtained from interp. fn step(&mut self, interp: &mut Interpreter, context: &mut EvmContext<'_, DB>) { self.gas_inspector.step(interp, context); - self.stack = interp.stack.clone(); + self.stack = interp.stack.data().clone(); self.pc = interp.program_counter(); self.opcode = interp.current_opcode(); self.mem_size = interp.shared_memory.len(); @@ -121,7 +121,7 @@ impl Inspector for TracerEip3155 { impl TracerEip3155 { fn print_log_line(&mut self, depth: u64, _memory: &[u8]) { - let short_stack: Vec = self.stack.data().iter().map(|&b| short_hex(b)).collect(); + let short_stack: Vec = self.stack.iter().map(|&b| short_hex(b)).collect(); let log_line = json!({ "depth": depth, "pc": self.pc, From 01cfef4c0ec3a980d121af4bce548cd1bb53db6e Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 22 Nov 2023 21:49:54 +0100 Subject: [PATCH 2/2] use alloc --- crates/interpreter/src/interpreter/stack.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index 7b82b5ceed..7a05ad0840 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -318,7 +318,7 @@ impl<'de> serde::Deserialize<'de> for Stack { { let mut data = Vec::::deserialize(deserializer)?; if data.len() > STACK_LIMIT { - return Err(serde::de::Error::custom(format!( + return Err(serde::de::Error::custom(alloc::format!( "stack size exceeds limit: {} > {}", data.len(), STACK_LIMIT