Skip to content

Commit

Permalink
fix: bail incomplete bytecode sequence disassemble (#9390)
Browse files Browse the repository at this point in the history
  • Loading branch information
publicqi authored Nov 25, 2024
1 parent 4923529 commit cca72ab
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
21 changes: 20 additions & 1 deletion crates/cast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,7 @@ impl SimpleCast {
pub fn disassemble(code: &[u8]) -> Result<String> {
let mut output = String::new();

for step in decode_instructions(code) {
for step in decode_instructions(code)? {
write!(output, "{:08x}: ", step.pc)?;

if let Some(op) = step.op {
Expand Down Expand Up @@ -2290,4 +2290,23 @@ mod tests {
r#"["0x2b5df5f0757397573e8ff34a8b987b21680357de1f6c8d10273aa528a851eaca","0x","0x","0x2838ac1d2d2721ba883169179b48480b2ba4f43d70fcf806956746bd9e83f903","0x","0xe46fff283b0ab96a32a7cc375cecc3ed7b6303a43d64e0a12eceb0bc6bd87549","0x","0x1d818c1c414c665a9c9a0e0c0ef1ef87cacb380b8c1f6223cb2a68a4b2d023f5","0x","0x","0x","0x236e8f61ecde6abfebc6c529441f782f62469d8a2cc47b7aace2c136bd3b1ff0","0x","0x","0x","0x","0x"]"#
)
}

#[test]
fn disassemble_incomplete_sequence() {
let incomplete = &hex!("60"); // PUSH1
let disassembled = Cast::disassemble(incomplete);
assert!(disassembled.is_err());

let complete = &hex!("6000"); // PUSH1 0x00
let disassembled = Cast::disassemble(complete);
assert!(disassembled.is_ok());

let incomplete = &hex!("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // PUSH32 with 31 bytes
let disassembled = Cast::disassemble(incomplete);
assert!(disassembled.is_err());

let complete = &hex!("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); // PUSH32 with 32 bytes
let disassembled = Cast::disassemble(complete);
assert!(disassembled.is_ok());
}
}
9 changes: 7 additions & 2 deletions crates/evm/core/src/ic.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use alloy_primitives::map::HashMap;
use eyre::Result;
use revm::interpreter::{
opcode::{PUSH0, PUSH1, PUSH32},
OpCode,
Expand Down Expand Up @@ -100,18 +101,22 @@ pub struct Instruction<'a> {
}

/// Decodes raw opcode bytes into [`Instruction`]s.
pub fn decode_instructions(code: &[u8]) -> Vec<Instruction<'_>> {
pub fn decode_instructions(code: &[u8]) -> Result<Vec<Instruction<'_>>> {
let mut pc = 0;
let mut steps = Vec::new();

while pc < code.len() {
let op = OpCode::new(code[pc]);
let immediate_size = op.map(|op| immediate_size(op, &code[pc + 1..])).unwrap_or(0) as usize;

if pc + 1 + immediate_size > code.len() {
eyre::bail!("incomplete sequence of bytecode");
}

steps.push(Instruction { op, pc, immediate: &code[pc + 1..pc + 1 + immediate_size] });

pc += 1 + immediate_size;
}

steps
Ok(steps)
}

0 comments on commit cca72ab

Please sign in to comment.