Skip to content

Commit

Permalink
fix: Only add unmapped instructions at the opcode boundary (#680)
Browse files Browse the repository at this point in the history
* fix: Only add unmapped instructions at the opcode boundary

* Add a changeset file

* Add a unit test for mapping instructions across opcode boundary
  • Loading branch information
Xanewok authored Sep 25, 2024
1 parent debac88 commit af56289
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/dirty-phones-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@nomicfoundation/edr": patch
---

fix(tracing): Decode unmapped instructions only at the opcode boundary
40 changes: 37 additions & 3 deletions crates/edr_solidity/src/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,11 @@ fn uncompress_sourcemaps(compressed: &str) -> Vec<SourceMap> {
}

fn add_unmapped_instructions(instructions: &mut Vec<Instruction>, bytecode: &[u8]) {
let last_instr_pc = instructions.last().map_or(0, |instr| instr.pc);

let mut bytes_index = (last_instr_pc + 1) as usize;
let mut bytes_index = instructions.last().map_or(0, |instr| {
// On the odd chance that the last instruction is a PUSH, we make sure
// to include any immediate data that might be present.
instr.pc as usize + 1 + instr.opcode.info().immediate_size() as usize
});

while bytecode.get(bytes_index) != Some(OpCode::INVALID.get()).as_ref() {
let opcode = OpCode::new(bytecode[bytes_index]).expect("Invalid opcode");
Expand Down Expand Up @@ -207,3 +209,35 @@ pub fn decode_instructions(

instructions
}

#[cfg(test)]
mod tests {
use edr_evm::interpreter::opcode;

use super::*;

#[test]
fn unmapped_instruction_opcode_boundary() {
let bytecode = &[opcode::PUSH2, 0xde, 0xad, opcode::STOP, opcode::INVALID];

let mut instructions = vec![Instruction {
pc: 0,
opcode: OpCode::PUSH2,
jump_type: JumpType::NotJump,
push_data: Some(vec![0xde, 0xad]),
location: None,
}];

// Make sure we start decoding from opcode::STOP rather than from inside
// the push data.
add_unmapped_instructions(&mut instructions, bytecode);

assert!(matches!(
instructions.last(),
Some(Instruction {
opcode: OpCode::STOP,
..
})
));
}
}

0 comments on commit af56289

Please sign in to comment.