Skip to content

Commit

Permalink
⚡ perf: remove/cleanup RLP encoded mess
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon-Becker committed Jul 6, 2023
1 parent 0a7629f commit cd67e01
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 69 deletions.
2 changes: 1 addition & 1 deletion common/src/ether/evm/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ pub fn find_cast(line: String) -> (usize, usize, Option<String>) {
let cast_type = line[start..].split('(').collect::<Vec<&str>>()[0].to_string();

// find where the cast ends
let (a, b, _) = find_balanced_encapsulator(line[end..].to_string(), ('(', ')'));
let (a, b, _) = find_balanced_encapsulator(&line[end..], ('(', ')'));
(end + a, end + b, Some(cast_type))
}
None => (0, 0, None),
Expand Down
9 changes: 3 additions & 6 deletions common/src/utils/strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ pub fn replace_last(s: String, old: &str, new: &str) -> String {
/// assert_eq!(end, 9);
/// assert_eq!(is_balanced, true);
/// ```
pub fn find_balanced_encapsulator(s: String, encap: (char, char)) -> (usize, usize, bool) {
pub fn find_balanced_encapsulator(s: &str, encap: (char, char)) -> (usize, usize, bool) {
let mut open = 0;
let mut close = 0;
let mut start = 0;
Expand Down Expand Up @@ -209,10 +209,7 @@ pub fn find_balanced_encapsulator(s: String, encap: (char, char)) -> (usize, usi
/// assert_eq!(end, 9);
/// assert_eq!(is_balanced, true);
/// ```
pub fn find_balanced_encapsulator_backwards(
s: String,
encap: (char, char),
) -> (usize, usize, bool) {
pub fn find_balanced_encapsulator_backwards(s: &str, encap: (char, char)) -> (usize, usize, bool) {
let mut open = 0;
let mut close = 0;
let mut start = 0;
Expand Down Expand Up @@ -339,7 +336,7 @@ pub fn extract_condition(s: &str, keyword: &str) -> Option<String> {
let sliced = s[start + keyword.len()..].to_string();

// find the balanced encapsulator
let (start, end, is_balanced) = find_balanced_encapsulator(sliced.clone(), ('(', ')'));
let (start, end, is_balanced) = find_balanced_encapsulator(&sliced, ('(', ')'));

// extract the condition if balanced encapsulator is found
if is_balanced {
Expand Down
12 changes: 6 additions & 6 deletions common/src/utils/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,21 +146,21 @@ mod test_strings {
fn test_find_balanced_encapsulator() {
let s = String::from("This is (an example) string.");
let encap = ('(', ')');
let (start, end, is_balanced) = find_balanced_encapsulator(s, encap);
let (start, end, is_balanced) = find_balanced_encapsulator(&s, encap);
assert_eq!(start, 8);
assert_eq!(end, 20);
assert_eq!(is_balanced, true);

let s = String::from("This is an example) string.");
let encap = ('(', ')');
let (start, end, is_balanced) = find_balanced_encapsulator(s, encap);
let (start, end, is_balanced) = find_balanced_encapsulator(&s, encap);
assert_eq!(start, 0);
assert_eq!(end, 1);
assert_eq!(is_balanced, false);

let s = String::from("This is (an example string.");
let encap = ('(', ')');
let (start, end, is_balanced) = find_balanced_encapsulator(s, encap);
let (start, end, is_balanced) = find_balanced_encapsulator(&s, encap);
assert_eq!(start, 8);
assert_eq!(end, 1);
assert_eq!(is_balanced, false);
Expand All @@ -170,19 +170,19 @@ mod test_strings {
fn test_find_balanced_encapsulator_backwards() {
let s = String::from("This is (an example) string.");
let encap = ('(', ')');
let (start, end, is_balanced) = find_balanced_encapsulator_backwards(s, encap);
let (start, end, is_balanced) = find_balanced_encapsulator_backwards(&s, encap);
assert_eq!(start, 8);
assert_eq!(end, 20);
assert_eq!(is_balanced, true);

let s = String::from("This is an example) string.");
let encap = ('(', ')');
let (_, _, is_balanced) = find_balanced_encapsulator_backwards(s, encap);
let (_, _, is_balanced) = find_balanced_encapsulator_backwards(&s, encap);
assert_eq!(is_balanced, false);

let s = String::from("This is (an example string.");
let encap = ('(', ')');
let (_, _, is_balanced) = find_balanced_encapsulator_backwards(s, encap);
let (_, _, is_balanced) = find_balanced_encapsulator_backwards(&s, encap);
assert_eq!(is_balanced, false);
}

Expand Down
34 changes: 17 additions & 17 deletions heimdall/src/decompile/lexers/solidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ impl VMTrace {
/// - `trace_parent` - The parent of the current VMTrace
/// - `branch` - Branch metadata for the current trace. In the format of (branch_depth,
/// branch_index)
/// - @jon-becker: This will be used later to determin if a condition is a require
///
///
/// ## Returns
/// - `function` - The function updated with the analysis results
Expand All @@ -35,8 +37,6 @@ impl VMTrace {
conditional_map: &mut Vec<String>,
branch: (u32, u8),
) -> Function {
println!("analyzing branch: {:?}", branch);

// make a clone of the recursed analysis function
let mut function = function;
let mut jumped_conditional: Option<String> = None;
Expand Down Expand Up @@ -189,9 +189,6 @@ impl VMTrace {
} else if opcode_name == "JUMPI" {
// this is an if conditional for the children branches
let conditional = instruction.input_operations[1].solidify();
function
.logic
.push(format!("// cnd {conditional} // branch {branch:?}").to_string());

// remove non-payable check and mark function as non-payable
if conditional == "!msg.value" {
Expand Down Expand Up @@ -327,7 +324,7 @@ impl VMTrace {
.iter()
.map(|x| x.operations.solidify())
.collect::<Vec<String>>()
.join("");
.join(", ");

// we don't want to overwrite the return value if it's already been set
if function.returns == Some(String::from("uint256")) || function.returns.is_none() {
Expand Down Expand Up @@ -362,8 +359,13 @@ impl VMTrace {
};
}
}

function.logic.push(format!("return({return_memory_operations_solidified});"));
if return_memory_operations.len() <= 1 {
function.logic.push(format!("return {return_memory_operations_solidified};"));
} else {
function.logic.push(format!(
"return abi.encodePacked({return_memory_operations_solidified});"
));
}
} else if opcode_name == "SELDFESTRUCT" {
let addr = match decode_hex(&instruction.inputs[0].encode_hex()) {
Ok(hex_data) => match decode(&[ParamType::Address], &hex_data) {
Expand All @@ -389,7 +391,7 @@ impl VMTrace {
} else if opcode_name.contains("MSTORE") {
let key = instruction.inputs[0];
let value = instruction.inputs[1];
let operation: WrappedOpcode = instruction.input_operations[1].clone();
let operation = instruction.input_operations[1].clone();

// add the mstore to the function's memory map
function.memory.insert(key, StorageFrame { value: value, operations: operation });
Expand Down Expand Up @@ -461,14 +463,14 @@ impl VMTrace {
}
_ => {
function.logic.push(format!(
"(bool success, bytes memory ret0) = address({}).staticcall{}({});",
"(bool success, bytes memory ret0) = address({}).staticcall{}(abi.encode({}));",
address.solidify(),
modifier,
extcalldata_memory
.iter()
.map(|x| x.operations.solidify())
.collect::<Vec<String>>()
.join(""),
.join(", "),
));
}
}
Expand Down Expand Up @@ -497,14 +499,14 @@ impl VMTrace {
}
_ => {
function.logic.push(format!(
"(bool success, bytes memory ret0) = address({}).delegatecall{}({});",
"(bool success, bytes memory ret0) = address({}).delegatecall{}(abi.encode({}));",
address.solidify(),
modifier,
extcalldata_memory
.iter()
.map(|x| x.operations.solidify())
.collect::<Vec<String>>()
.join(""),
.join(", "),
));
}
}
Expand Down Expand Up @@ -541,14 +543,14 @@ impl VMTrace {
}
_ => {
function.logic.push(format!(
"(bool success, bytes memory ret0) = address({}).call{}({});",
"(bool success, bytes memory ret0) = address({}).call{}(abi.encode({}));",
address.solidify(),
modifier,
extcalldata_memory
.iter()
.map(|x| x.operations.solidify())
.collect::<Vec<String>>()
.join("")
.join(", ")
));
}
}
Expand Down Expand Up @@ -752,8 +754,6 @@ impl VMTrace {
function.logic.push("}".to_string());
}

function.logic.push(format!("// branch {branch:?} end", branch = branch));

function
}
}
15 changes: 5 additions & 10 deletions heimdall/src/decompile/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,10 +455,8 @@ pub fn decompile(args: DecompilerArgs) {
let resolved_errors: HashMap<String, Vec<ResolvedError>> = resolve_selectors(
analyzed_function
.errors
.iter()
.map(|(error_selector, _)| {
encode_hex_reduced(*error_selector).replacen("0x", "", 1)
})
.keys()
.map(|error_selector| encode_hex_reduced(*error_selector).replacen("0x", "", 1))
.collect(),
&logger,
);
Expand Down Expand Up @@ -526,17 +524,14 @@ pub fn decompile(args: DecompilerArgs) {
let resolved_events: HashMap<String, Vec<ResolvedLog>> = resolve_selectors(
analyzed_function
.events
.iter()
.map(|(event_selector, _)| {
encode_hex_reduced(*event_selector).replacen("0x", "", 1)
})
.keys()
.map(|event_selector| encode_hex_reduced(*event_selector).replacen("0x", "", 1))
.collect(),
&logger,
);
for (event_selector, (_, raw_event)) in analyzed_function.events.clone() {
let mut selected_event_index: u8 = 0;
let event_selector_str =
encode_hex_reduced(event_selector.clone()).replacen("0x", "", 1);
let event_selector_str = encode_hex_reduced(event_selector).replacen("0x", "", 1);
let mut resolved_event_selectors = match resolved_events.get(&event_selector_str) {
Some(func) => func.clone(),
None => Vec::new(),
Expand Down
33 changes: 12 additions & 21 deletions heimdall/src/decompile/out/postprocessers/solidity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ fn convert_bitmask_to_casting(line: String) -> String {
let mut subject = cleaned.get(bitmask.end()..).unwrap().replace(';', "");

// attempt to find matching parentheses
let subject_indices = find_balanced_encapsulator(subject.to_string(), ('(', ')'));
let subject_indices = find_balanced_encapsulator(&subject, ('(', ')'));
subject = match subject_indices.2 {
true => {
// get the subject as hte substring between the balanced parentheses found in
Expand Down Expand Up @@ -110,8 +110,7 @@ fn convert_bitmask_to_casting(line: String) -> String {
};

// attempt to find matching parentheses
let subject_indices =
find_balanced_encapsulator_backwards(subject.to_string(), ('(', ')'));
let subject_indices = find_balanced_encapsulator_backwards(&subject, ('(', ')'));

subject = match subject_indices.2 {
true => {
Expand Down Expand Up @@ -252,7 +251,7 @@ fn simplify_parentheses(line: String, paren_index: usize) -> String {
};

let inner_tokens = tokenize(&inside);
return !inner_tokens.iter().any(|tk| classify_token(&tk) == TokenType::Operator)
return !inner_tokens.iter().any(|tk| classify_token(tk) == TokenType::Operator)
}

let mut cleaned = line;
Expand All @@ -270,7 +269,7 @@ fn simplify_parentheses(line: String, paren_index: usize) -> String {

//find it's matching close paren
let (paren_start, paren_end, found_match) =
find_balanced_encapsulator(cleaned[nth_paren_index..].to_string(), ('(', ')'));
find_balanced_encapsulator(&cleaned[nth_paren_index..], ('(', ')'));

// add the nth open paren to the start of the paren_start
let paren_start = paren_start + nth_paren_index;
Expand Down Expand Up @@ -360,7 +359,7 @@ fn convert_access_to_variable(line: String) -> String {
};

// since the regex is greedy, match the memory brackets
let matched_loc = find_balanced_encapsulator(memory_access.to_string(), ('[', ']'));
let matched_loc = find_balanced_encapsulator(memory_access, ('[', ']'));
if let true = matched_loc.2 {
let mut mem_map = MEM_LOOKUP_MAP.lock().unwrap();

Expand Down Expand Up @@ -399,7 +398,7 @@ fn convert_access_to_variable(line: String) -> String {
};

// since the regex is greedy, match the memory brackets
let matched_loc = find_balanced_encapsulator(storage_access.to_string(), ('[', ']'));
let matched_loc = find_balanced_encapsulator(storage_access, ('[', ']'));
if let true = matched_loc.2 {
let mut stor_map = STORAGE_LOOKUP_MAP.lock().unwrap();

Expand All @@ -415,7 +414,7 @@ fn convert_access_to_variable(line: String) -> String {

// get the variable name
if memloc.contains("keccak256") {
let keccak_key = find_balanced_encapsulator(memloc.clone(), ('(', ')'));
let keccak_key = find_balanced_encapsulator(&memloc, ('(', ')'));

let variable_name = format!(
"stor_map_{}[{}]",
Expand Down Expand Up @@ -453,7 +452,6 @@ fn convert_access_to_variable(line: String) -> String {

let mut var_map = VARIABLE_MAP.lock().unwrap();
var_map.insert(instantiation[0].clone(), instantiation[1].replace(';', ""));

drop(var_map);
} else {
// if var_map doesn't contain the variable, add it
Expand Down Expand Up @@ -501,13 +499,8 @@ fn convert_access_to_variable(line: String) -> String {
/// assert_eq!(contains_unnecessary_assignment(line, &lines), true);
/// ```
fn contains_unnecessary_assignment(line: String, lines: &Vec<&String>) -> bool {
// skip lines that don't contain an assignment
if !line.contains(" = ") {
return false
}

// skip lines that contain external calls
if line.contains("bool success") {
// skip lines that don't contain an assignment, or contain a return or external calls
if !line.contains(" = ") || line.contains("bool success") || line.contains("return") {
return false
}

Expand Down Expand Up @@ -576,7 +569,7 @@ fn move_casts_to_declaration(line: String) -> String {

// find the matching close paren
let (paren_start, paren_end, _) =
find_balanced_encapsulator(instantiation[1].to_string(), ('(', ')'));
find_balanced_encapsulator(&instantiation[1], ('(', ')'));

// the close paren must be at the end of the expression
if paren_end != instantiation[1].len() - 1 {
Expand Down Expand Up @@ -732,7 +725,7 @@ fn inherit_infer_storage_type(line: String) {
};

// since the regex is greedy, match the memory brackets
let matched_loc = find_balanced_encapsulator(storage_access.to_string(), ('[', ']'));
let matched_loc = find_balanced_encapsulator(&storage_access, ('[', ']'));
if !matched_loc.2 {
return
}
Expand Down Expand Up @@ -919,9 +912,7 @@ fn simplify_arithmatic(line: String) -> String {
let cleaned = MUL_BY_ONE_REGEX.replace_all(&cleaned, "");

// remove double negation
let cleaned = cleaned.replace("!!", "");

cleaned.to_string()
cleaned.replace("!!", "")
}

fn cleanup(
Expand Down
Loading

0 comments on commit cd67e01

Please sign in to comment.