Unverified Commit ffb08bc4 by Enkelmann Committed by GitHub

Minor project struct refactoring (#231)

parent 26f2f4f0
...@@ -164,8 +164,8 @@ fn run_with_ghidra(args: &CmdlineArgs) { ...@@ -164,8 +164,8 @@ fn run_with_ghidra(args: &CmdlineArgs) {
.program .program
.term .term
.extern_symbols .extern_symbols
.iter() .keys()
.map(|symbol| symbol.tid.clone()) .cloned()
.collect(); .collect();
let control_flow_graph = graph::get_program_cfg(&project.program, extern_sub_tids); let control_flow_graph = graph::get_program_cfg(&project.program, extern_sub_tids);
......
use crate::intermediate_representation::*;
use super::{create_computation, mock_context, NodeValue}; use super::{create_computation, mock_context, NodeValue};
use crate::intermediate_representation::*;
use std::collections::BTreeMap;
use mock_context::Context; use mock_context::Context;
use mock_context::StartEnd; use mock_context::StartEnd;
...@@ -128,7 +128,7 @@ fn mock_program() -> Term<Program> { ...@@ -128,7 +128,7 @@ fn mock_program() -> Term<Program> {
tid: Tid::new("program"), tid: Tid::new("program"),
term: Program { term: Program {
subs: vec![sub1, sub2], subs: vec![sub1, sub2],
extern_symbols: Vec::new(), extern_symbols: BTreeMap::new(),
entry_points: Vec::new(), entry_points: Vec::new(),
address_base_offset: 0, address_base_offset: 0,
}, },
......
...@@ -18,8 +18,8 @@ pub fn compute_alive_vars(project: &Project) -> HashMap<Tid, HashSet<Variable>> ...@@ -18,8 +18,8 @@ pub fn compute_alive_vars(project: &Project) -> HashMap<Tid, HashSet<Variable>>
.program .program
.term .term
.extern_symbols .extern_symbols
.iter() .keys()
.map(|symbol| symbol.tid.clone()) .cloned()
.collect(); .collect();
let mut graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs); let mut graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs);
graph.reverse(); graph.reverse();
......
...@@ -497,6 +497,7 @@ pub fn get_program_cfg(program: &Term<Program>, extern_subs: HashSet<Tid>) -> Gr ...@@ -497,6 +497,7 @@ pub fn get_program_cfg(program: &Term<Program>, extern_subs: HashSet<Tid>) -> Gr
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use std::collections::BTreeMap;
fn mock_program() -> Term<Program> { fn mock_program() -> Term<Program> {
let call_term = Term { let call_term = Term {
...@@ -577,7 +578,7 @@ mod tests { ...@@ -577,7 +578,7 @@ mod tests {
tid: Tid::new("program"), tid: Tid::new("program"),
term: Program { term: Program {
subs: vec![sub1, sub2], subs: vec![sub1, sub2],
extern_symbols: Vec::new(), extern_symbols: BTreeMap::new(),
entry_points: Vec::new(), entry_points: Vec::new(),
address_base_offset: 0, address_base_offset: 0,
}, },
......
...@@ -26,7 +26,7 @@ pub struct Context<'a> { ...@@ -26,7 +26,7 @@ pub struct Context<'a> {
/// Note that values of writeable global memory segments are not tracked. /// Note that values of writeable global memory segments are not tracked.
pub runtime_memory_image: &'a RuntimeMemoryImage, pub runtime_memory_image: &'a RuntimeMemoryImage,
/// Maps the TIDs of functions that shall be treated as extern symbols to the `ExternSymbol` object representing it. /// Maps the TIDs of functions that shall be treated as extern symbols to the `ExternSymbol` object representing it.
pub extern_symbol_map: BTreeMap<Tid, &'a ExternSymbol>, pub extern_symbol_map: &'a BTreeMap<Tid, ExternSymbol>,
/// A channel where found CWE warnings and log messages should be sent to. /// A channel where found CWE warnings and log messages should be sent to.
/// The receiver may filter or modify the warnings before presenting them to the user. /// The receiver may filter or modify the warnings before presenting them to the user.
/// For example, the same CWE warning will be found several times /// For example, the same CWE warning will be found several times
...@@ -49,15 +49,11 @@ impl<'a> Context<'a> { ...@@ -49,15 +49,11 @@ impl<'a> Context<'a> {
config: Config, config: Config,
log_collector: crossbeam_channel::Sender<LogThreadMsg>, log_collector: crossbeam_channel::Sender<LogThreadMsg>,
) -> Context<'a> { ) -> Context<'a> {
let mut extern_symbol_map = BTreeMap::new();
for symbol in project.program.term.extern_symbols.iter() {
extern_symbol_map.insert(symbol.tid.clone(), symbol);
}
Context { Context {
graph: control_flow_graph, graph: control_flow_graph,
project, project,
runtime_memory_image, runtime_memory_image,
extern_symbol_map, extern_symbol_map: &project.program.term.extern_symbols,
log_collector, log_collector,
allocation_symbols: config.allocation_symbols, allocation_symbols: config.allocation_symbols,
deallocation_symbols: config.deallocation_symbols, deallocation_symbols: config.deallocation_symbols,
......
...@@ -14,21 +14,25 @@ fn new_id(time: &str, reg_name: &str) -> AbstractIdentifier { ...@@ -14,21 +14,25 @@ fn new_id(time: &str, reg_name: &str) -> AbstractIdentifier {
) )
} }
fn mock_extern_symbol(name: &str) -> ExternSymbol { fn mock_extern_symbol(name: &str) -> (Tid, ExternSymbol) {
let arg = Arg::Register { let arg = Arg::Register {
var: register("RDX"), var: register("RDX"),
data_type: None, data_type: None,
}; };
ExternSymbol { let tid = Tid::new("extern_".to_string() + name);
tid: Tid::new("extern_".to_string() + name), (
addresses: vec![], tid.clone(),
name: name.into(), ExternSymbol {
calling_convention: None, tid,
parameters: vec![arg.clone()], addresses: vec![],
return_values: vec![arg], name: name.into(),
no_return: false, calling_convention: None,
has_var_args: false, parameters: vec![arg.clone()],
} return_values: vec![arg],
no_return: false,
has_var_args: false,
},
)
} }
fn register(name: &str) -> Variable { fn register(name: &str) -> Variable {
...@@ -77,7 +81,9 @@ fn mock_project() -> (Project, Config) { ...@@ -77,7 +81,9 @@ fn mock_project() -> (Project, Config) {
mock_extern_symbol("malloc"), mock_extern_symbol("malloc"),
mock_extern_symbol("free"), mock_extern_symbol("free"),
mock_extern_symbol("other"), mock_extern_symbol("other"),
], ]
.into_iter()
.collect(),
entry_points: Vec::new(), entry_points: Vec::new(),
address_base_offset: 0, address_base_offset: 0,
}; };
......
...@@ -267,13 +267,7 @@ impl<'a> PointerInference<'a> { ...@@ -267,13 +267,7 @@ impl<'a> PointerInference<'a> {
// TODO: Refactor the fixpoint computation structs, so that the project reference can be extracted from them. // TODO: Refactor the fixpoint computation structs, so that the project reference can be extracted from them.
let mut start_block_to_sub_map: HashMap<&Tid, &Term<Sub>> = HashMap::new(); let mut start_block_to_sub_map: HashMap<&Tid, &Term<Sub>> = HashMap::new();
for sub in project.program.term.subs.iter() { for sub in project.program.term.subs.iter() {
if project if project.program.term.extern_symbols.contains_key(&sub.tid) {
.program
.term
.extern_symbols
.iter()
.any(|symbol| symbol.tid == sub.tid)
{
continue; // We ignore functions marked as extern symbols. continue; // We ignore functions marked as extern symbols.
} }
if let Some(start_block) = sub.term.blocks.first() { if let Some(start_block) = sub.term.blocks.first() {
......
...@@ -81,7 +81,7 @@ pub fn check_cwe( ...@@ -81,7 +81,7 @@ pub fn check_cwe(
.term .term
.extern_symbols .extern_symbols
.iter() .iter()
.map(|symbol| (symbol.name.as_str(), symbol.tid.clone())) .map(|(tid, symbol)| (symbol.name.as_str(), tid.clone()))
.collect(); .collect();
for (source, sink) in config.pairs { for (source, sink) in config.pairs {
......
...@@ -87,8 +87,8 @@ impl<'a> Context<'a> { ...@@ -87,8 +87,8 @@ impl<'a> Context<'a> {
} }
} }
let mut extern_symbol_map = HashMap::new(); let mut extern_symbol_map = HashMap::new();
for symbol in project.program.term.extern_symbols.iter() { for (tid, symbol) in project.program.term.extern_symbols.iter() {
extern_symbol_map.insert(symbol.tid.clone(), symbol); extern_symbol_map.insert(tid.clone(), symbol);
} }
Context { Context {
project, project,
...@@ -112,14 +112,8 @@ impl<'a> Context<'a> { ...@@ -112,14 +112,8 @@ impl<'a> Context<'a> {
.program .program
.term .term
.extern_symbols .extern_symbols
.iter() .get(target)
.find_map(|symb| { .map(|symbol| symbol.name.clone())
if symb.tid == *target {
Some(symb.name.clone())
} else {
None
}
})
.unwrap_or_else(|| "Unknown".to_string()), .unwrap_or_else(|| "Unknown".to_string()),
_ => "Unknown".to_string(), _ => "Unknown".to_string(),
}; };
......
...@@ -19,7 +19,7 @@ False Negatives ...@@ -19,7 +19,7 @@ False Negatives
* None known * None known
*/ */
use crate::prelude::*; use crate::prelude::*;
use std::collections::HashMap; use std::collections::{BTreeMap, HashMap, HashSet};
use crate::{ use crate::{
intermediate_representation::{ExternSymbol, Program, Sub, Term, Tid}, intermediate_representation::{ExternSymbol, Program, Sub, Term, Tid},
...@@ -48,15 +48,11 @@ pub struct Config { ...@@ -48,15 +48,11 @@ pub struct Config {
/// For each subroutine and each found dangerous symbol, check for calls to the corresponding symbol /// For each subroutine and each found dangerous symbol, check for calls to the corresponding symbol
pub fn get_calls<'a>( pub fn get_calls<'a>(
subfunctions: &'a [Term<Sub>], subfunctions: &'a [Term<Sub>],
dangerous_symbols: &'a [&'a ExternSymbol], dangerous_symbols: &'a HashMap<&'a Tid, &'a str>,
) -> Vec<(&'a str, &'a Tid, &'a str)> { ) -> Vec<(&'a str, &'a Tid, &'a str)> {
let mut calls: Vec<(&str, &Tid, &str)> = Vec::new(); let mut calls: Vec<(&str, &Tid, &str)> = Vec::new();
let mut symbol_map: HashMap<&Tid, &str> = HashMap::with_capacity(dangerous_symbols.len());
for symbol in dangerous_symbols.iter() {
symbol_map.insert(&symbol.tid, symbol.name.as_str());
}
for sub in subfunctions.iter() { for sub in subfunctions.iter() {
calls.append(&mut get_calls_to_symbols(sub, &symbol_map)); calls.append(&mut get_calls_to_symbols(sub, dangerous_symbols));
} }
calls calls
...@@ -95,15 +91,16 @@ pub fn generate_cwe_warnings<'a>( ...@@ -95,15 +91,16 @@ pub fn generate_cwe_warnings<'a>(
/// Filter external symbols by dangerous symbols /// Filter external symbols by dangerous symbols
pub fn resolve_symbols<'a>( pub fn resolve_symbols<'a>(
external_symbols: &'a [ExternSymbol], external_symbols: &'a BTreeMap<Tid, ExternSymbol>,
symbols: &'a [String], symbols: &'a [String],
) -> Vec<&'a ExternSymbol> { ) -> HashMap<&'a Tid, &'a str> {
let dangerous_symbols: HashSet<&'a String> = symbols.iter().collect();
external_symbols external_symbols
.iter() .iter()
.filter(|symbol| { .filter_map(|(tid, symbol)| {
symbols dangerous_symbols
.iter() .get(&symbol.name)
.any(|dangerous_function| *symbol.name == *dangerous_function) .map(|name| (tid, name.as_str()))
}) })
.collect() .collect()
} }
...@@ -118,7 +115,7 @@ pub fn check_cwe( ...@@ -118,7 +115,7 @@ pub fn check_cwe(
let config: Config = serde_json::from_value(cwe_params.clone()).unwrap(); let config: Config = serde_json::from_value(cwe_params.clone()).unwrap();
let prog: &Term<Program> = &project.program; let prog: &Term<Program> = &project.program;
let subfunctions: &Vec<Term<Sub>> = &prog.term.subs; let subfunctions: &Vec<Term<Sub>> = &prog.term.subs;
let external_symbols: &Vec<ExternSymbol> = &prog.term.extern_symbols; let external_symbols: &BTreeMap<Tid, ExternSymbol> = &prog.term.extern_symbols;
let dangerous_symbols = resolve_symbols(external_symbols, &config.symbols); let dangerous_symbols = resolve_symbols(external_symbols, &config.symbols);
let dangerous_calls = get_calls(subfunctions, &dangerous_symbols); let dangerous_calls = get_calls(subfunctions, &dangerous_symbols);
......
...@@ -232,8 +232,8 @@ impl<'a> SymbolMaps<'a> { ...@@ -232,8 +232,8 @@ impl<'a> SymbolMaps<'a> {
/// Creates a new instance of the symbol maps struct. /// Creates a new instance of the symbol maps struct.
pub fn new(project: &'a Project, config: &Config) -> Self { pub fn new(project: &'a Project, config: &Config) -> Self {
let mut extern_symbol_map = HashMap::new(); let mut extern_symbol_map = HashMap::new();
for symbol in project.program.term.extern_symbols.iter() { for (tid, symbol) in project.program.term.extern_symbols.iter() {
extern_symbol_map.insert(symbol.tid.clone(), symbol); extern_symbol_map.insert(tid.clone(), symbol);
} }
SymbolMaps { SymbolMaps {
string_symbol_map: crate::utils::symbol_utils::get_symbol_map( string_symbol_map: crate::utils::symbol_utils::get_symbol_map(
......
...@@ -103,12 +103,12 @@ impl Setup { ...@@ -103,12 +103,12 @@ impl Setup {
.program .program
.term .term
.extern_symbols .extern_symbols
.push(ExternSymbol::mock_string()); .insert(ExternSymbol::mock_string().tid, ExternSymbol::mock_string());
project project
.program .program
.term .term
.extern_symbols .extern_symbols
.push(ExternSymbol::mock()); .insert(ExternSymbol::mock().tid, ExternSymbol::mock());
project.program.term.subs.push(sub); project.program.term.subs.push(sub);
project.program.term.entry_points.push(Tid::new("func")); project.program.term.entry_points.push(Tid::new("func"));
project.calling_conventions.push(CallingConvention::mock()); project.calling_conventions.push(CallingConvention::mock());
...@@ -138,8 +138,8 @@ impl<'a> Context<'a> { ...@@ -138,8 +138,8 @@ impl<'a> Context<'a> {
graph.reverse(); graph.reverse();
let mut extern_symbol_map = HashMap::new(); let mut extern_symbol_map = HashMap::new();
for symbol in project.program.term.extern_symbols.iter() { for (tid, symbol) in project.program.term.extern_symbols.iter() {
extern_symbol_map.insert(symbol.tid.clone(), symbol); extern_symbol_map.insert(tid.clone(), symbol);
} }
let mut block_first_def_set: HashSet<(Tid, Tid)> = HashSet::new(); let mut block_first_def_set: HashSet<(Tid, Tid)> = HashSet::new();
......
use super::{Blk, ExternSymbol, Sub}; use super::{Blk, ExternSymbol, Sub};
use crate::prelude::*; use crate::prelude::*;
use std::collections::BTreeMap;
/// The `Program` structure represents a disassembled binary. /// The `Program` structure represents a disassembled binary.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Program { pub struct Program {
/// The known functions contained in the binary /// The known functions contained in the binary
pub subs: Vec<Term<Sub>>, pub subs: Vec<Term<Sub>>,
/// Extern symbols linked to the binary by the linker. /// Extern symbols linked to the binary by the linker.
pub extern_symbols: Vec<ExternSymbol>, pub extern_symbols: BTreeMap<Tid, ExternSymbol>,
/// Entry points into to binary, /// Entry points into to binary,
/// i.e. the term identifiers of functions that may be called from outside of the binary. /// i.e. the term identifiers of functions that may be called from outside of the binary.
pub entry_points: Vec<Tid>, pub entry_points: Vec<Tid>,
...@@ -42,7 +43,7 @@ mod tests { ...@@ -42,7 +43,7 @@ mod tests {
pub fn mock_empty() -> Program { pub fn mock_empty() -> Program {
Program { Program {
subs: Vec::new(), subs: Vec::new(),
extern_symbols: Vec::new(), extern_symbols: BTreeMap::new(),
entry_points: Vec::new(), entry_points: Vec::new(),
address_base_offset: 0, address_base_offset: 0,
} }
......
...@@ -10,7 +10,7 @@ use block_duplication_normalization::*; ...@@ -10,7 +10,7 @@ use block_duplication_normalization::*;
/// ///
/// It contains information about the disassembled binary /// It contains information about the disassembled binary
/// and about the execution environment of the binary. /// and about the execution environment of the binary.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Hash, Clone)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Project { pub struct Project {
/// All (known) executable code of the binary is contained in the `program` term. /// All (known) executable code of the binary is contained in the `program` term.
pub program: Term<Program>, pub program: Term<Program>,
...@@ -89,8 +89,8 @@ impl Project { ...@@ -89,8 +89,8 @@ impl Project {
jump_target_tids.insert(block.tid.clone()); jump_target_tids.insert(block.tid.clone());
} }
} }
for symbol in self.program.term.extern_symbols.iter() { for symbol_tid in self.program.term.extern_symbols.keys() {
jump_target_tids.insert(symbol.tid.clone()); jump_target_tids.insert(symbol_tid.clone());
} }
// Replace all jumps to non-existing jump targets with jumps to dummy targets // Replace all jumps to non-existing jump targets with jumps to dummy targets
let dummy_sub_tid = Tid::new("Artificial Sink Sub"); let dummy_sub_tid = Tid::new("Artificial Sink Sub");
......
...@@ -610,7 +610,12 @@ impl Program { ...@@ -610,7 +610,12 @@ impl Program {
let extern_symbols = self let extern_symbols = self
.extern_symbols .extern_symbols
.into_iter() .into_iter()
.map(|symbol| symbol.into_ir_symbol(conventions, stack_pointer, cpu_arch)) .map(|symbol| {
(
symbol.tid.clone(),
symbol.into_ir_symbol(conventions, stack_pointer, cpu_arch),
)
})
.collect(); .collect();
let address_base_offset = let address_base_offset =
u64::from_str_radix(&self.image_base, 16).unwrap() - binary_base_address; u64::from_str_radix(&self.image_base, 16).unwrap() - binary_base_address;
......
...@@ -8,9 +8,12 @@ use crate::intermediate_representation::*; ...@@ -8,9 +8,12 @@ use crate::intermediate_representation::*;
/// Find the extern symbol object for a symbol name and return the symbol tid and name. /// Find the extern symbol object for a symbol name and return the symbol tid and name.
pub fn find_symbol<'a>(prog: &'a Term<Program>, name: &str) -> Option<(&'a Tid, &'a str)> { pub fn find_symbol<'a>(prog: &'a Term<Program>, name: &str) -> Option<(&'a Tid, &'a str)> {
let mut symbol: Option<(&'a Tid, &'a str)> = None; let mut symbol: Option<(&'a Tid, &'a str)> = None;
prog.term.extern_symbols.iter().for_each(|sym| { prog.term.extern_symbols.iter().find(|(_tid, sym)| {
if name == sym.name { if name == sym.name {
symbol = Some((&sym.tid, &sym.name)); symbol = Some((&sym.tid, &sym.name));
true
} else {
false
} }
}); });
...@@ -46,18 +49,19 @@ pub fn get_symbol_map<'a>( ...@@ -46,18 +49,19 @@ pub fn get_symbol_map<'a>(
) -> HashMap<Tid, &'a ExternSymbol> { ) -> HashMap<Tid, &'a ExternSymbol> {
let mut tid_map = HashMap::new(); let mut tid_map = HashMap::new();
for symbol_name in symbols_to_find { for symbol_name in symbols_to_find {
if let Some((tid, symbol)) = project if let Some((tid, symbol)) =
.program project
.term .program
.extern_symbols .term
.iter() .extern_symbols
.find_map(|symbol| { .iter()
if symbol.name == *symbol_name { .find_map(|(_tid, symbol)| {
Some((symbol.tid.clone(), symbol)) if symbol.name == *symbol_name {
} else { Some((symbol.tid.clone(), symbol))
None } else {
} None
}) }
})
{ {
tid_map.insert(tid, symbol); tid_map.insert(tid, symbol);
} }
......
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