Skip to content

Commit 0ff03fb

Browse files
committed
fix: when a node has already appeared, we will not add it to the graph
1 parent e8db827 commit 0ff03fb

File tree

2 files changed

+15
-2
lines changed

2 files changed

+15
-2
lines changed

crates/cfg/src/core/graph.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use heimdall_vm::{
66
ext::exec::VMTrace,
77
};
88
use petgraph::{matrix_graph::NodeIndex, Graph};
9+
use std::collections::HashSet;
910

1011
/// convert a symbolic execution [`VMTrace`] into a [`Graph`] of blocks, illustrating the
1112
/// control-flow graph found by the symbolic execution engine.
@@ -15,6 +16,7 @@ pub fn build_cfg(
1516
contract_cfg: &mut Graph<String, String>,
1617
parent_node: Option<NodeIndex<u32>>,
1718
jump_taken: bool,
19+
seen_nodes: &mut HashSet<String>,
1820
) -> Result<()> {
1921
let mut cfg_node: String = String::new();
2022
let mut parent_node = parent_node;
@@ -23,9 +25,11 @@ pub fn build_cfg(
2325
for operation in &vm_trace.operations {
2426
let opcode_name = opcode_name(operation.last_instruction.opcode);
2527

28+
let opcode_offset = operation.last_instruction.instruction - 1; // start from 0x00
29+
2630
let assembly = format!(
2731
"{} {} {}",
28-
encode_hex_reduced(U256::from(operation.last_instruction.instruction - 1)), // start from 0x00
32+
encode_hex_reduced(U256::from(opcode_offset)),
2933
opcode_name,
3034
if opcode_name.contains("PUSH") {
3135
encode_hex_reduced(
@@ -42,6 +46,12 @@ pub fn build_cfg(
4246

4347
cfg_node.push_str(&format!("{}\n", &assembly));
4448
}
49+
50+
// check if this node has been seen before
51+
if seen_nodes.contains(&cfg_node) {
52+
return Ok(());
53+
}
54+
seen_nodes.insert(cfg_node.clone());
4555

4656
// add the node to the graph
4757
let node_index = contract_cfg.add_node(cfg_node);
@@ -63,6 +73,7 @@ pub fn build_cfg(
6373
.last_instruction
6474
.opcode ==
6575
JUMPDEST,
76+
seen_nodes,
6677
)?;
6778
}
6879

crates/cfg/src/core/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use alloy::primitives::Address;
44
use eyre::eyre;
55
use heimdall_common::{ether::compiler::detect_compiler, utils::strings::StringExt};
66
use heimdall_vm::core::vm::VM;
7+
use std::collections::HashSet;
78

89
use petgraph::{dot::Dot, Graph};
910
use std::time::{Duration, Instant};
@@ -93,7 +94,8 @@ pub async fn cfg(args: CfgArgs) -> Result<CfgResult, Error> {
9394
let start_cfg_time = Instant::now();
9495
info!("building cfg for '{}' from symbolic execution trace", args.target.truncate(64));
9596
let mut contract_cfg = Graph::new();
96-
build_cfg(&map, &mut contract_cfg, None, false)?;
97+
let mut seen_nodes: HashSet<String> = HashSet::new();
98+
build_cfg(&map, &mut contract_cfg, None, false, &mut seen_nodes)?;
9799
debug!("building cfg took {:?}", start_cfg_time.elapsed());
98100

99101
debug!("cfg generated in {:?}", start_time.elapsed());

0 commit comments

Comments
 (0)