Skip to content

Commit

Permalink
lib/ir/project: remove old jump targets pass
Browse files Browse the repository at this point in the history
  • Loading branch information
Valentin Obst committed Jul 23, 2024
1 parent d02b555 commit 3b7311b
Showing 1 changed file with 1 addition and 105 deletions.
106 changes: 1 addition & 105 deletions src/cwe_checker_lib/src/intermediate_representation/project.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::*;
use crate::analysis;
use crate::utils::log::LogMessage;
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::collections::{BTreeMap, BTreeSet, HashSet};

pub mod propagate_control_flow;
use propagate_control_flow::*;
Expand Down Expand Up @@ -242,57 +242,6 @@ impl Project {
.insert(Tid::artificial_sink_sub(), Term::<Sub>::artificial_sink());
}

/// Returns the set of all valid jump targets.
fn find_all_jump_targets(&self) -> HashSet<Tid> {
let mut jump_target_tids = HashSet::new();

for sub in self.program.term.subs.values() {
jump_target_tids.insert(sub.tid.clone());
for block in sub.term.blocks.iter() {
jump_target_tids.insert(block.tid.clone());
}
}

for symbol_tid in self.program.term.extern_symbols.keys() {
jump_target_tids.insert(symbol_tid.clone());
}

jump_target_tids
}

/// Replace jumps to nonexisting TIDs with jumps to a dummy target
/// representing an artificial sink in the control flow graph.
/// Return a log message for each replaced jump target.
///
/// Nonexisting jump targets may be generated by the Ghidra backend
/// if the data at the target address is not a valid assembly instruction.
#[must_use]
fn remove_references_to_nonexisting_tids(&mut self) -> Vec<LogMessage> {
let mut log_messages = Vec::new();
let all_jump_targets = self.find_all_jump_targets();

// Replace all jumps to non-existing jump targets with jumps to dummy
// targets.
for sub in self.program.term.subs.values_mut() {
for block in sub.term.blocks.iter_mut() {
if let Err(mut logs) =
block.remove_nonexisting_indirect_jump_targets(&all_jump_targets)
{
log_messages.append(&mut logs);
}
for jmp in block.term.jmps.iter_mut() {
if let Err(log_msg) =
jmp.retarget_nonexisting_jump_targets_to_artificial_sink(&all_jump_targets)
{
log_messages.push(log_msg);
}
}
}
}

log_messages
}

/// Remove blocks, defs and jumps with duplicate TIDs and return log messages on such cases.
/// Since such cases break the fundamental invariant that each TID is unique,
/// they result in errors if not removed.
Expand Down Expand Up @@ -373,7 +322,6 @@ impl Project {
pub fn normalize_basic(&mut self) -> Vec<LogMessage> {
let mut logs = self.remove_duplicate_tids();
self.add_artifical_sink();
logs.append(self.remove_references_to_nonexisting_tids().as_mut());
logs.append(
self.retarget_non_returning_calls_to_artificial_sink()
.as_mut(),
Expand Down Expand Up @@ -421,58 +369,6 @@ impl Project {
}
}

impl Term<Jmp> {
/// If the TID of a jump target, call target, or return target is not
/// contained in in the known jump targets, replace it with a dummy TID and
/// return an error message.
fn retarget_nonexisting_jump_targets_to_artificial_sink(
&mut self,
all_jump_targets: &HashSet<Tid>,
) -> Result<(), LogMessage> {
use Jmp::*;
match &mut self.term {
BranchInd(_) => Ok(()),
Branch(tid) | CBranch { target: tid, .. } if !all_jump_targets.contains(tid) => {
let error_msg = format!("Jump target at {} does not exist", tid.address);
let error_log = LogMessage::new_error(error_msg).location(self.tid.clone());

*tid = Tid::artificial_sink_block("");

Err(error_log)
}
Call { target, return_ } if !all_jump_targets.contains(target) => {
let error_msg = format!("Call target at {} does not exist", target.address);
let error_log = LogMessage::new_error(error_msg).location(self.tid.clone());

*target = Tid::artificial_sink_sub();
*return_ = None;

Err(error_log)
}
Call {
return_: Some(return_tid),
..
}
| CallInd {
return_: Some(return_tid),
..
}
| CallOther {
return_: Some(return_tid),
..
} if !all_jump_targets.contains(return_tid) => {
let error_msg = format!("Return target at {} does not exist", return_tid.address);
let error_log = LogMessage::new_error(error_msg).location(self.tid.clone());

*return_tid = Tid::artificial_sink_block("");

Err(error_log)
}
_ => Ok(()),
}
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down

0 comments on commit 3b7311b

Please sign in to comment.