Skip to content

Commit

Permalink
fix: safer stack
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse committed Nov 22, 2023
1 parent de0b2f4 commit 9cdd725
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 8 deletions.
31 changes: 28 additions & 3 deletions crates/interpreter/src/interpreter/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<U256>,
Expand Down Expand Up @@ -64,6 +64,12 @@ impl Stack {
&self.data
}

/// Consumes the stack and returns the underlying data.
#[inline]
pub fn into_data(self) -> Vec<U256> {
self.data
}

/// Removes the topmost element from the stack and returns it, or `StackUnderflow` if it is
/// empty.
#[inline]
Expand Down Expand Up @@ -304,6 +310,25 @@ impl Stack {
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Stack {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let mut data = Vec::<U256>::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::*;
Expand Down
10 changes: 5 additions & 5 deletions crates/revm/src/inspector/eip3155.rs
Original file line number Diff line number Diff line change
@@ -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,
};
Expand All @@ -18,7 +18,7 @@ pub struct TracerEip3155 {
#[allow(dead_code)]
trace_return_data: bool,

stack: Stack,
stack: Vec<U256>,
pc: usize,
opcode: u8,
gas: u64,
Expand All @@ -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,
Expand All @@ -52,7 +52,7 @@ impl<DB: Database> Inspector<DB> 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();
Expand Down Expand Up @@ -121,7 +121,7 @@ impl<DB: Database> Inspector<DB> for TracerEip3155 {

impl TracerEip3155 {
fn print_log_line(&mut self, depth: u64, _memory: &[u8]) {
let short_stack: Vec<String> = self.stack.data().iter().map(|&b| short_hex(b)).collect();
let short_stack: Vec<String> = self.stack.iter().map(|&b| short_hex(b)).collect();
let log_line = json!({
"depth": depth,
"pc": self.pc,
Expand Down

0 comments on commit 9cdd725

Please sign in to comment.