Unverified Commit 7afcd9e8 by van den Bosch Committed by GitHub

Small code refactorings (#396)

parent 1450ae08
...@@ -130,14 +130,8 @@ fn run_with_ghidra(args: &CmdlineArgs) -> Result<(), Error> { ...@@ -130,14 +130,8 @@ fn run_with_ghidra(args: &CmdlineArgs) -> Result<(), Error> {
disassemble_binary(&binary_file_path, bare_metal_config_opt, args.verbose)?; disassemble_binary(&binary_file_path, bare_metal_config_opt, args.verbose)?;
// Generate the control flow graph of the program // Generate the control flow graph of the program
let extern_sub_tids = project let (control_flow_graph, mut logs_graph) = graph::get_program_cfg_with_logs(&project.program);
.program all_logs.append(&mut logs_graph);
.term
.extern_symbols
.keys()
.cloned()
.collect();
let control_flow_graph = graph::get_program_cfg(&project.program, extern_sub_tids);
let analysis_results = AnalysisResults::new(&binary, &control_flow_graph, &project); let analysis_results = AnalysisResults::new(&binary, &control_flow_graph, &project);
...@@ -204,6 +198,7 @@ fn run_with_ghidra(args: &CmdlineArgs) -> Result<(), Error> { ...@@ -204,6 +198,7 @@ fn run_with_ghidra(args: &CmdlineArgs) -> Result<(), Error> {
all_logs.append(&mut logs); all_logs.append(&mut logs);
all_cwes.append(&mut cwes); all_cwes.append(&mut cwes);
} }
all_cwes.sort();
// Print the results of the modules. // Print the results of the modules.
if args.quiet { if args.quiet {
......
use super::*; use super::*;
use crate::analysis::graph::Graph; use crate::analysis::graph::Graph;
use petgraph::graph::NodeIndex; use petgraph::graph::NodeIndex;
use std::collections::{HashMap, HashSet}; use std::collections::HashMap;
/// Identifier for BlkStart and BlkEnd nodes /// Identifier for BlkStart and BlkEnd nodes
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash)]
...@@ -19,7 +19,7 @@ pub struct Context<'a> { ...@@ -19,7 +19,7 @@ pub struct Context<'a> {
impl<'a> Context<'a> { impl<'a> Context<'a> {
pub fn new(project: &'a Project) -> Self { pub fn new(project: &'a Project) -> Self {
let mut graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new()); let mut graph = crate::analysis::graph::get_program_cfg(&project.program);
graph.reverse(); graph.reverse();
let mut tid_to_node_index: HashMap<(Tid, Tid, StartEnd), NodeIndex> = HashMap::new(); let mut tid_to_node_index: HashMap<(Tid, Tid, StartEnd), NodeIndex> = HashMap::new();
for node in graph.node_indices() { for node in graph.node_indices() {
......
...@@ -14,14 +14,7 @@ use alive_vars_computation::*; ...@@ -14,14 +14,7 @@ use alive_vars_computation::*;
/// Returns a map that assigns to each basic block `Tid` the set of all variables /// Returns a map that assigns to each basic block `Tid` the set of all variables
/// that are alive at the end of the basic block. /// that are alive at the end of the basic block.
pub fn compute_alive_vars(project: &Project) -> HashMap<Tid, BTreeSet<Variable>> { pub fn compute_alive_vars(project: &Project) -> HashMap<Tid, BTreeSet<Variable>> {
let extern_subs = project let mut graph = crate::analysis::graph::get_program_cfg(&project.program);
.program
.term
.extern_symbols
.keys()
.cloned()
.collect();
let mut graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs);
graph.reverse(); graph.reverse();
let context = Context::new(project, &graph); let context = Context::new(project, &graph);
let all_physical_registers = context.all_physical_registers.clone(); let all_physical_registers = context.all_physical_registers.clone();
......
...@@ -330,16 +330,9 @@ pub fn merge_def_assignments_to_same_var(blk: &mut Term<Blk>) { ...@@ -330,16 +330,9 @@ pub fn merge_def_assignments_to_same_var(blk: &mut Term<Blk>) {
/// ///
/// This is performed by a fixpoint computation and might panic, if it does not stabilize. /// This is performed by a fixpoint computation and might panic, if it does not stabilize.
pub fn propagate_input_expression(project: &mut Project) { pub fn propagate_input_expression(project: &mut Project) {
let extern_subs = project
.program
.term
.extern_symbols
.keys()
.cloned()
.collect();
merge_same_var_assignments(project); merge_same_var_assignments(project);
let graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs); let graph = crate::analysis::graph::get_program_cfg(&project.program);
let computation = compute_expression_propagation(&graph); let computation = compute_expression_propagation(&graph);
let results = extract_results(&graph, computation); let results = extract_results(&graph, computation);
insert_expressions(results, &mut project.program.term); insert_expressions(results, &mut project.program.term);
......
...@@ -176,15 +176,7 @@ fn no_propagation_on_calls() { ...@@ -176,15 +176,7 @@ fn no_propagation_on_calls() {
/// variable-expressions pairs. /// variable-expressions pairs.
fn insertion_table_update() { fn insertion_table_update() {
let project = &mock_project(); let project = &mock_project();
let extern_subs = project let graph = crate::analysis::graph::get_program_cfg(&project.program);
.program
.term
.extern_symbols
.keys()
.cloned()
.collect();
let graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs);
let context = Context::new(&graph); let context = Context::new(&graph);
let blk = get_mock_entry_block().term; let blk = get_mock_entry_block().term;
......
...@@ -336,7 +336,7 @@ mod tests { ...@@ -336,7 +336,7 @@ mod tests {
expr, expr,
intermediate_representation::*, intermediate_representation::*,
}; };
use std::collections::{BTreeMap, HashMap, HashSet}; use std::collections::{BTreeMap, HashMap};
fn new_block(name: &str) -> Term<Blk> { fn new_block(name: &str) -> Term<Blk> {
Term { Term {
...@@ -403,9 +403,7 @@ mod tests { ...@@ -403,9 +403,7 @@ mod tests {
/// Checks if the nodes corresponding to the callee function are first in the worklist. /// Checks if the nodes corresponding to the callee function are first in the worklist.
fn check_bottom_up_worklist() { fn check_bottom_up_worklist() {
let project = mock_project(); let project = mock_project();
let extern_subs = HashSet::new(); let graph = crate::analysis::graph::get_program_cfg(&project.program);
let graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs);
let context = Context::new(&graph); let context = Context::new(&graph);
let comp = create_computation_with_bottom_up_worklist_order(context, Some(HashMap::new())); let comp = create_computation_with_bottom_up_worklist_order(context, Some(HashMap::new()));
// The last two nodes should belong to the callee // The last two nodes should belong to the callee
...@@ -423,9 +421,7 @@ mod tests { ...@@ -423,9 +421,7 @@ mod tests {
#[test] #[test]
fn check_top_down_worklist() { fn check_top_down_worklist() {
let project = mock_project(); let project = mock_project();
let extern_subs = HashSet::new(); let graph = crate::analysis::graph::get_program_cfg(&project.program);
let graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs);
let context = Context::new(&graph); let context = Context::new(&graph);
let comp = create_computation_with_top_down_worklist_order(context, Some(HashMap::new())); let comp = create_computation_with_top_down_worklist_order(context, Some(HashMap::new()));
// The first two nodes should belong to the callee // The first two nodes should belong to the callee
......
use super::*; use super::*;
use crate::{bitvec, variable}; use crate::{bitvec, variable};
use std::collections::HashSet;
#[test] #[test]
fn test_compute_return_values_of_call() { fn test_compute_return_values_of_call() {
let project = Project::mock_x64(); let project = Project::mock_x64();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new()); let graph = crate::analysis::graph::get_program_cfg(&project.program);
let context = Context::new(&project, &graph); let context = Context::new(&project, &graph);
...@@ -54,7 +53,7 @@ fn test_compute_return_values_of_call() { ...@@ -54,7 +53,7 @@ fn test_compute_return_values_of_call() {
#[test] #[test]
fn test_call_stub_handling() { fn test_call_stub_handling() {
let project = Project::mock_arm32(); let project = Project::mock_arm32();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new()); let graph = crate::analysis::graph::get_program_cfg(&project.program);
let context = Context::new(&project, &graph); let context = Context::new(&project, &graph);
...@@ -117,7 +116,7 @@ fn test_call_stub_handling() { ...@@ -117,7 +116,7 @@ fn test_call_stub_handling() {
#[test] #[test]
fn test_get_global_mem_address() { fn test_get_global_mem_address() {
let project = Project::mock_arm32(); let project = Project::mock_arm32();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new()); let graph = crate::analysis::graph::get_program_cfg(&project.program);
let context = Context::new(&project, &graph); let context = Context::new(&project, &graph);
// Check global address from abstract ID // Check global address from abstract ID
......
...@@ -44,6 +44,7 @@ ...@@ -44,6 +44,7 @@
use crate::intermediate_representation::*; use crate::intermediate_representation::*;
use crate::prelude::*; use crate::prelude::*;
use crate::utils::log::LogMessage;
use petgraph::graph::{DiGraph, NodeIndex}; use petgraph::graph::{DiGraph, NodeIndex};
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
...@@ -188,6 +189,8 @@ struct GraphBuilder<'a> { ...@@ -188,6 +189,8 @@ struct GraphBuilder<'a> {
return_addresses: HashMap<Tid, Vec<(NodeIndex, NodeIndex)>>, return_addresses: HashMap<Tid, Vec<(NodeIndex, NodeIndex)>>,
/// A list of `BlkEnd` nodes for which outgoing edges still have to be added to the graph. /// A list of `BlkEnd` nodes for which outgoing edges still have to be added to the graph.
block_worklist: Vec<NodeIndex>, block_worklist: Vec<NodeIndex>,
/// List of `LogMessage` generated by `build` function.
log_messages: Vec<LogMessage>,
} }
impl<'a> GraphBuilder<'a> { impl<'a> GraphBuilder<'a> {
...@@ -201,6 +204,7 @@ impl<'a> GraphBuilder<'a> { ...@@ -201,6 +204,7 @@ impl<'a> GraphBuilder<'a> {
jump_targets: HashMap::new(), jump_targets: HashMap::new(),
return_addresses: HashMap::new(), return_addresses: HashMap::new(),
block_worklist: Vec::new(), block_worklist: Vec::new(),
log_messages: Vec::new(),
} }
} }
...@@ -237,8 +241,12 @@ impl<'a> GraphBuilder<'a> { ...@@ -237,8 +241,12 @@ impl<'a> GraphBuilder<'a> {
let start_block = &sub.term.blocks[0]; let start_block = &sub.term.blocks[0];
let target_index = self.jump_targets[&(start_block.tid.clone(), sub.tid.clone())]; let target_index = self.jump_targets[&(start_block.tid.clone(), sub.tid.clone())];
self.call_targets.insert(sub.tid.clone(), target_index); self.call_targets.insert(sub.tid.clone(), target_index);
} else {
self.log_messages.push(LogMessage::new_info(format!(
"{} contains no blocks",
sub.tid
)))
} }
// TODO: Generate Log-Message for Subs without blocks.
} }
} }
...@@ -479,19 +487,25 @@ impl<'a> GraphBuilder<'a> { ...@@ -479,19 +487,25 @@ impl<'a> GraphBuilder<'a> {
} }
/// Build the interprocedural control flow graph. /// Build the interprocedural control flow graph.
pub fn build(mut self) -> Graph<'a> { pub fn build(&mut self) -> Graph<'a> {
self.add_program_blocks(); self.add_program_blocks();
self.add_subs_to_call_targets(); self.add_subs_to_call_targets();
self.add_jump_and_call_edges(); self.add_jump_and_call_edges();
self.add_return_edges(); self.add_return_edges();
self.graph self.graph.clone()
} }
} }
/// Build the interprocedural control flow graph for a program term. /// Build the interprocedural control flow graph for a program term.
pub fn get_program_cfg(program: &Term<Program>, extern_subs: HashSet<Tid>) -> Graph { pub fn get_program_cfg(program: &Term<Program>) -> Graph {
let builder = GraphBuilder::new(program, extern_subs); get_program_cfg_with_logs(program).0
builder.build() }
/// Build the interprocedural control flow graph for a program term with log messages created by building.
pub fn get_program_cfg_with_logs(program: &Term<Program>) -> (Graph, Vec<LogMessage>) {
let extern_subs = program.term.extern_symbols.keys().cloned().collect();
let mut builder = GraphBuilder::new(program, extern_subs);
(builder.build(), builder.log_messages)
} }
/// Returns a map from function TIDs to the node index of the `BlkStart` node of the first block in the function. /// Returns a map from function TIDs to the node index of the `BlkStart` node of the first block in the function.
...@@ -610,7 +624,7 @@ mod tests { ...@@ -610,7 +624,7 @@ mod tests {
#[test] #[test]
fn create_program_cfg() { fn create_program_cfg() {
let program = mock_program(); let program = mock_program();
let graph = get_program_cfg(&program, HashSet::new()); let graph = get_program_cfg(&program);
println!("{}", serde_json::to_string_pretty(&graph).unwrap()); println!("{}", serde_json::to_string_pretty(&graph).unwrap());
assert_eq!(graph.node_count(), 16); assert_eq!(graph.node_count(), 16);
assert_eq!(graph.edge_count(), 20); assert_eq!(graph.edge_count(), 20);
...@@ -646,7 +660,7 @@ mod tests { ...@@ -646,7 +660,7 @@ mod tests {
tid: Tid::new("program".to_string()), tid: Tid::new("program".to_string()),
term: program, term: program,
}; };
let graph = get_program_cfg(&program_term, HashSet::new()); let graph = get_program_cfg(&program_term);
assert_eq!(graph.node_count(), 2); assert_eq!(graph.node_count(), 2);
assert_eq!(graph.edge_count(), 2); assert_eq!(graph.edge_count(), 2);
} }
......
...@@ -89,7 +89,6 @@ pub fn check_cwe( ...@@ -89,7 +89,6 @@ pub fn check_cwe(
fixpoint_computation.compute_with_max_steps(100); fixpoint_computation.compute_with_max_steps(100);
let (logs, mut cwe_warnings) = log_thread.collect(); let (logs, cwe_warnings) = log_thread.collect();
cwe_warnings.sort();
(logs, cwe_warnings) (logs, cwe_warnings)
} }
...@@ -105,7 +105,6 @@ pub fn check_cwe( ...@@ -105,7 +105,6 @@ pub fn check_cwe(
} }
} }
cwe_warnings.sort();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -176,8 +175,6 @@ fn generate_cwe_warning( ...@@ -176,8 +175,6 @@ fn generate_cwe_warning(
#[cfg(test)] #[cfg(test)]
pub mod tests { pub mod tests {
use std::collections::HashSet;
use crate::analysis::pointer_inference::PointerInference as PointerInferenceComputation; use crate::analysis::pointer_inference::PointerInference as PointerInferenceComputation;
use crate::{defs, intermediate_representation::*}; use crate::{defs, intermediate_representation::*};
...@@ -209,7 +206,7 @@ pub mod tests { ...@@ -209,7 +206,7 @@ pub mod tests {
fn test_locate_format_string() { fn test_locate_format_string() {
let sprintf_symbol = ExternSymbol::mock_sprintf_x64(); let sprintf_symbol = ExternSymbol::mock_sprintf_x64();
let project = mock_project(); let project = mock_project();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new()); let graph = crate::analysis::graph::get_program_cfg(&project.program);
let mut pi_results = PointerInferenceComputation::mock(&project); let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute(false); pi_results.compute(false);
let mut format_string_index: HashMap<String, usize> = HashMap::new(); let mut format_string_index: HashMap<String, usize> = HashMap::new();
......
...@@ -175,6 +175,5 @@ pub fn check_cwe( ...@@ -175,6 +175,5 @@ pub fn check_cwe(
} }
} }
cwe_warnings.sort();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -175,6 +175,5 @@ pub fn check_cwe( ...@@ -175,6 +175,5 @@ pub fn check_cwe(
} }
} }
cwe_warnings.sort();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -68,6 +68,5 @@ pub fn check_cwe( ...@@ -68,6 +68,5 @@ pub fn check_cwe(
cwe_warnings.push(generate_cwe_warning(secure_initializer_func, rand_func)); cwe_warnings.push(generate_cwe_warning(secure_initializer_func, rand_func));
} }
} }
cwe_warnings.sort();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -119,6 +119,5 @@ pub fn check_cwe( ...@@ -119,6 +119,5 @@ pub fn check_cwe(
} }
} }
cwe_warnings.sort();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -78,7 +78,6 @@ pub fn check_cwe( ...@@ -78,7 +78,6 @@ pub fn check_cwe(
} }
fixpoint_computation.compute_with_max_steps(100); fixpoint_computation.compute_with_max_steps(100);
let (logs, mut cwe_warnings) = log_thread.collect(); let (logs, cwe_warnings) = log_thread.collect();
cwe_warnings.sort();
(logs, cwe_warnings) (logs, cwe_warnings)
} }
...@@ -96,6 +96,5 @@ pub fn check_cwe( ...@@ -96,6 +96,5 @@ pub fn check_cwe(
} }
} }
} }
cwe_warnings.sort();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -120,6 +120,5 @@ pub fn check_cwe( ...@@ -120,6 +120,5 @@ pub fn check_cwe(
} }
} }
} }
cwe_warnings.sort();
(Vec::new(), cwe_warnings) (Vec::new(), cwe_warnings)
} }
...@@ -133,6 +133,5 @@ pub fn check_cwe( ...@@ -133,6 +133,5 @@ pub fn check_cwe(
} }
} }
cwes.sort();
(log_messages, cwes) (log_messages, cwes)
} }
...@@ -84,7 +84,6 @@ pub fn generate_cwe_warnings<'a>( ...@@ -84,7 +84,6 @@ pub fn generate_cwe_warnings<'a>(
cwe_warnings.push(cwe_warning); cwe_warnings.push(cwe_warning);
} }
cwe_warnings.sort();
cwe_warnings cwe_warnings
} }
......
...@@ -80,6 +80,6 @@ pub fn check_cwe( ...@@ -80,6 +80,6 @@ pub fn check_cwe(
.values() .values()
.for_each(|sub| warnings.append(&mut handle_sub(sub, symbol))); .for_each(|sub| warnings.append(&mut handle_sub(sub, symbol)));
} }
warnings.sort();
(vec![], warnings) (vec![], warnings)
} }
...@@ -16,14 +16,7 @@ use std::collections::{BTreeSet, HashMap, HashSet}; ...@@ -16,14 +16,7 @@ use std::collections::{BTreeSet, HashMap, HashSet};
/// For such a sequence we then retarget the destination of the first jump to the final jump destination of the sequence. /// For such a sequence we then retarget the destination of the first jump to the final jump destination of the sequence.
/// Lastly, the newly bypassed blocks are considered dead code and are removed. /// Lastly, the newly bypassed blocks are considered dead code and are removed.
pub fn propagate_control_flow(project: &mut Project) { pub fn propagate_control_flow(project: &mut Project) {
let extern_subs: HashSet<Tid> = project let cfg = crate::analysis::graph::get_program_cfg(&project.program);
.program
.term
.extern_symbols
.keys()
.cloned()
.collect();
let cfg = crate::analysis::graph::get_program_cfg(&project.program, extern_subs.clone());
let nodes_without_incoming_edges_at_beginning = get_nodes_without_incoming_edge(&cfg); let nodes_without_incoming_edges_at_beginning = get_nodes_without_incoming_edge(&cfg);
let mut jmps_to_retarget = HashMap::new(); let mut jmps_to_retarget = HashMap::new();
...@@ -75,7 +68,7 @@ pub fn propagate_control_flow(project: &mut Project) { ...@@ -75,7 +68,7 @@ pub fn propagate_control_flow(project: &mut Project) {
} }
retarget_jumps(project, jmps_to_retarget); retarget_jumps(project, jmps_to_retarget);
let cfg = crate::analysis::graph::get_program_cfg(&project.program, extern_subs); let cfg = crate::analysis::graph::get_program_cfg(&project.program);
let nodes_without_incoming_edges_at_end = get_nodes_without_incoming_edge(&cfg); let nodes_without_incoming_edges_at_end = get_nodes_without_incoming_edge(&cfg);
remove_new_orphaned_blocks( remove_new_orphaned_blocks(
......
...@@ -123,15 +123,12 @@ impl<'a> AnalysisResults<'a> { ...@@ -123,15 +123,12 @@ impl<'a> AnalysisResults<'a> {
mod tests { mod tests {
use super::*; use super::*;
use crate::analysis::graph::get_program_cfg; use crate::analysis::graph::get_program_cfg;
use std::collections::HashSet;
impl<'a> AnalysisResults<'a> { impl<'a> AnalysisResults<'a> {
/// Mocks the `AnalysisResults` struct with a given project. /// Mocks the `AnalysisResults` struct with a given project.
/// Note that the function leaks memory! /// Note that the function leaks memory!
pub fn mock_from_project(project: &'a Project) -> AnalysisResults<'a> { pub fn mock_from_project(project: &'a Project) -> AnalysisResults<'a> {
let extern_subs = let graph = Box::new(get_program_cfg(&project.program));
HashSet::from_iter(project.program.term.extern_symbols.keys().cloned());
let graph = Box::new(get_program_cfg(&project.program, extern_subs));
let graph: &'a Graph = Box::leak(graph); let graph: &'a Graph = Box::leak(graph);
let binary: &'a Vec<u8> = Box::leak(Box::new(Vec::new())); let binary: &'a Vec<u8> = Box::leak(Box::new(Vec::new()));
let analysis_results = AnalysisResults::new(binary, graph, project); let analysis_results = AnalysisResults::new(binary, graph, project);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment