Unverified Commit 41f10fa1 by Enkelmann Committed by GitHub

prepare usage of FunctionSignature analysis in PointerInference (#277)

parent 7b6c6f4a
......@@ -10,7 +10,7 @@ use cwe_checker_lib::utils::{get_ghidra_plugin_path, read_config_file};
use cwe_checker_lib::AnalysisResults;
use cwe_checker_lib::{intermediate_representation::Project, utils::log::LogMessage};
use nix::{sys::stat, unistd};
use std::collections::HashSet;
use std::collections::{BTreeSet, HashSet};
use std::path::{Path, PathBuf};
use std::process::Command;
use std::thread;
......@@ -176,8 +176,9 @@ fn run_with_ghidra(args: &CmdlineArgs) {
&project,
);
let modules_depending_on_string_abstraction = vec!["CWE78"];
let modules_depending_on_pointer_inference = vec!["CWE134", "CWE476", "Memory"];
let modules_depending_on_string_abstraction = BTreeSet::from_iter(["CWE78"]);
let modules_depending_on_pointer_inference =
BTreeSet::from_iter(["CWE134", "CWE476", "Memory"]);
let string_abstraction_needed = modules
.iter()
......@@ -188,14 +189,23 @@ fn run_with_ghidra(args: &CmdlineArgs) {
.iter()
.any(|module| modules_depending_on_pointer_inference.contains(&module.name));
// Compute function signatures if required
let function_signatures = if pi_analysis_needed {
let (function_signatures, mut logs) = analysis_results.compute_function_signatures();
all_logs.append(&mut logs);
Some(function_signatures)
} else {
None
};
let analysis_results = analysis_results.with_function_signatures(function_signatures.as_ref());
// Compute pointer inference if required
let pi_analysis_results = if pi_analysis_needed {
Some(analysis_results.compute_pointer_inference(&config["Memory"], args.statistics))
} else {
None
};
let analysis_results = analysis_results.set_pointer_inference(pi_analysis_results.as_ref());
let analysis_results = analysis_results.with_pointer_inference(pi_analysis_results.as_ref());
// Compute string abstraction analysis if required
let string_abstraction_results =
if string_abstraction_needed {
Some(analysis_results.compute_string_abstraction(
......@@ -205,18 +215,15 @@ fn run_with_ghidra(args: &CmdlineArgs) {
} else {
None
};
let analysis_results =
analysis_results.set_string_abstraction(string_abstraction_results.as_ref());
analysis_results.with_string_abstraction(string_abstraction_results.as_ref());
// Print debug and then return.
// Right now there is only one debug printing function.
// When more debug printing modes exist, this behaviour will change!
if args.debug {
cwe_checker_lib::analysis::pointer_inference::run(
&project,
&runtime_memory_image,
&control_flow_graph,
&analysis_results,
serde_json::from_value(config["Memory"].clone()).unwrap(),
true,
false,
......
......@@ -62,7 +62,9 @@ fn generate_fixpoint_computation<'a>(
NodeValue::Value(State::new(
&sub.tid,
&project.stack_pointer_register,
project.get_standard_calling_convention().unwrap(),
project
.get_specific_calling_convention(&sub.term.calling_convention)
.unwrap(),
)),
)
}
......@@ -129,7 +131,7 @@ fn extract_fn_signatures_from_fixpoint<'a>(
pub fn compute_function_signatures<'a>(
project: &'a Project,
graph: &'a Graph,
) -> (Vec<LogMessage>, BTreeMap<Tid, FunctionSignature>) {
) -> (BTreeMap<Tid, FunctionSignature>, Vec<LogMessage>) {
let mut computation = generate_fixpoint_computation(project, graph);
computation.compute_with_max_steps(100);
let mut fn_sig_map = extract_fn_signatures_from_fixpoint(project, graph, computation);
......@@ -145,7 +147,7 @@ pub fn compute_function_signatures<'a>(
}
}
(logs, fn_sig_map)
(fn_sig_map, logs)
}
/// The signature of a function.
......
use super::object::ObjectType;
use crate::analysis::function_signature::FunctionSignature;
use crate::analysis::graph::Graph;
use crate::intermediate_representation::*;
use crate::prelude::*;
......@@ -27,6 +28,8 @@ pub struct Context<'a> {
pub runtime_memory_image: &'a RuntimeMemoryImage,
/// Maps the TIDs of functions that shall be treated as extern symbols to the `ExternSymbol` object representing it.
pub extern_symbol_map: &'a BTreeMap<Tid, ExternSymbol>,
/// Maps the TIDs of internal functions to the function signatures computed for it.
pub fn_signatures: &'a BTreeMap<Tid, FunctionSignature>,
/// 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.
/// For example, the same CWE warning will be found several times
......@@ -43,17 +46,16 @@ impl<'a> Context<'a> {
/// Create a new context object for a given project.
/// Also needs two channels as input to know where CWE warnings and log messages should be sent to.
pub fn new(
project: &'a Project,
runtime_memory_image: &'a RuntimeMemoryImage,
control_flow_graph: &'a Graph<'a>,
analysis_results: &'a AnalysisResults<'a>,
config: Config,
log_collector: crossbeam_channel::Sender<LogThreadMsg>,
) -> Context<'a> {
Context {
graph: control_flow_graph,
project,
runtime_memory_image,
extern_symbol_map: &project.program.term.extern_symbols,
graph: analysis_results.control_flow_graph,
project: analysis_results.project,
runtime_memory_image: analysis_results.runtime_memory_image,
extern_symbol_map: &analysis_results.project.program.term.extern_symbols,
fn_signatures: analysis_results.function_signatures.unwrap(),
log_collector,
allocation_symbols: config.allocation_symbols,
deallocation_symbols: config.deallocation_symbols,
......
use crate::intermediate_representation::DatatypeProperties;
use super::*;
use std::{collections::HashSet, iter::FromIterator};
use crate::intermediate_representation::DatatypeProperties;
fn bv(value: i64) -> ValueDomain {
ValueDomain::from(Bitvector::from_i64(value))
......@@ -126,10 +124,9 @@ fn context_problem_implementation() {
use Expression::*;
let (project, config) = mock_project();
let runtime_memory_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let (log_sender, _log_receiver) = crossbeam_channel::unbounded();
let context = Context::new(&project, &runtime_memory_image, &graph, config, log_sender);
let analysis_results = AnalysisResults::mock_from_project(&project);
let context = Context::new(&analysis_results, config, log_sender);
let mut state = State::new(&register("RSP"), Tid::new("main"));
let def = Term {
......@@ -287,10 +284,9 @@ fn update_return() {
use crate::analysis::pointer_inference::object::ObjectType;
use crate::analysis::pointer_inference::Data;
let (project, config) = mock_project();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let runtime_memory_image = RuntimeMemoryImage::mock();
let (log_sender, _log_receiver) = crossbeam_channel::unbounded();
let context = Context::new(&project, &runtime_memory_image, &graph, config, log_sender);
let analysis_results = AnalysisResults::mock_from_project(&project);
let context = Context::new(&analysis_results, config, log_sender);
let state_before_return = State::new(&register("RSP"), Tid::new("callee"));
let mut state_before_return = context
.update_def(
......@@ -387,10 +383,9 @@ fn update_return() {
fn specialize_conditional() {
use crate::analysis::forward_interprocedural_fixpoint::Context as IpFpContext;
let (project, config) = mock_project();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let runtime_memory_image = RuntimeMemoryImage::mock();
let (log_sender, _log_receiver) = crossbeam_channel::unbounded();
let context = Context::new(&project, &runtime_memory_image, &graph, config, log_sender);
let analysis_results = AnalysisResults::mock_from_project(&project);
let context = Context::new(&analysis_results, config, log_sender);
let mut state = State::new(&register("RSP"), Tid::new("func"));
state.set_register(&register("RAX"), IntervalDomain::mock(-10, 20).into());
......
......@@ -29,14 +29,11 @@
use super::fixpoint::Computation;
use super::forward_interprocedural_fixpoint::GeneralizedContext;
use super::interprocedural_fixpoint_generic::NodeValue;
use crate::abstract_domain::{DataDomain, IntervalDomain};
use crate::analysis::graph::{Graph, Node};
use crate::intermediate_representation::*;
use crate::prelude::*;
use crate::utils::log::*;
use crate::{
abstract_domain::{DataDomain, IntervalDomain},
utils::binary::RuntimeMemoryImage,
};
use petgraph::graph::NodeIndex;
use petgraph::visit::IntoNodeReferences;
use petgraph::Direction;
......@@ -91,20 +88,13 @@ pub struct PointerInference<'a> {
impl<'a> PointerInference<'a> {
/// Generate a new pointer inference compuation for a project.
pub fn new(
project: &'a Project,
runtime_memory_image: &'a RuntimeMemoryImage,
control_flow_graph: &'a Graph<'a>,
analysis_results: &'a AnalysisResults<'a>,
config: Config,
log_sender: crossbeam_channel::Sender<LogThreadMsg>,
print_stats: bool,
) -> PointerInference<'a> {
let context = Context::new(
project,
runtime_memory_image,
control_flow_graph,
config,
log_sender.clone(),
);
let context = Context::new(analysis_results, config, log_sender.clone());
let project = analysis_results.project;
let mut entry_sub_to_entry_blocks_map = HashMap::new();
for sub_tid in project.program.term.entry_points.iter() {
......@@ -466,9 +456,7 @@ pub fn extract_pi_analysis_results(
/// If `print_debug` is set to `true` print debug information to *stdout*.
/// Note that the format of the debug information is currently unstable and subject to change.
pub fn run<'a>(
project: &'a Project,
runtime_memory_image: &'a RuntimeMemoryImage,
control_flow_graph: &'a Graph<'a>,
analysis_results: &'a AnalysisResults<'a>,
config: Config,
print_debug: bool,
print_stats: bool,
......@@ -476,15 +464,13 @@ pub fn run<'a>(
let logging_thread = LogThread::spawn(collect_all_logs);
let mut computation = PointerInference::new(
project,
runtime_memory_image,
control_flow_graph,
analysis_results,
config,
logging_thread.get_msg_sender(),
print_stats,
);
computation.compute_with_speculative_entry_points(project, print_stats);
computation.compute_with_speculative_entry_points(analysis_results.project, print_stats);
if print_debug {
computation.print_compact_json();
......@@ -541,17 +527,15 @@ mod tests {
use super::*;
impl<'a> PointerInference<'a> {
pub fn mock(
project: &'a Project,
mem_image: &'a RuntimeMemoryImage,
graph: &'a Graph,
) -> PointerInference<'a> {
pub fn mock(project: &'a Project) -> PointerInference<'a> {
let analysis_results = Box::new(AnalysisResults::mock_from_project(project));
let analysis_results: &'a AnalysisResults = Box::leak(analysis_results);
let config = Config {
allocation_symbols: vec!["malloc".to_string()],
deallocation_symbols: vec!["free".to_string()],
};
let (log_sender, _) = crossbeam_channel::unbounded();
PointerInference::new(project, mem_image, graph, config, log_sender, false)
PointerInference::new(analysis_results, config, log_sender, false)
}
pub fn set_node_value(&mut self, node_value: State, node_index: NodeIndex) {
......
......@@ -197,9 +197,6 @@ impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Conte
#[cfg(test)]
mod tests {
use std::collections::{BTreeMap, BTreeSet, HashSet};
use crate::{
abstract_domain::{
AbstractIdentifier, AbstractLocation, CharacterInclusionDomain, CharacterSet,
......@@ -210,8 +207,8 @@ mod tests {
tests::mock_project_with_intraprocedural_control_flow,
},
intermediate_representation::{Bitvector, Tid, Variable},
utils::binary::RuntimeMemoryImage,
};
use std::collections::{BTreeMap, BTreeSet};
use super::*;
......@@ -222,9 +219,7 @@ mod tests {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -287,9 +282,7 @@ mod tests {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -314,9 +307,7 @@ mod tests {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -344,9 +335,7 @@ mod tests {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -369,9 +358,7 @@ mod tests {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -413,9 +400,7 @@ mod tests {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -461,9 +446,7 @@ mod tests {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......
......@@ -191,17 +191,12 @@ impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Conte
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use super::super::tests::*;
use super::*;
use crate::abstract_domain::{AbstractIdentifier, AbstractLocation, CharacterInclusionDomain};
use crate::analysis::pointer_inference::PointerInference as PointerInferenceComputation;
use crate::analysis::string_abstraction::tests::mock_project_with_intraprocedural_control_flow;
use crate::intermediate_representation::{Expression, Variable};
use crate::utils::binary::RuntimeMemoryImage;
use super::super::tests::*;
use super::*;
#[test]
fn test_handle_scanf_calls() {
......@@ -211,9 +206,7 @@ mod tests {
vec![(scanf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -296,9 +289,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![true, true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -374,9 +365,7 @@ mod tests {
vec![(scanf_symbol.clone(), vec![false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -449,9 +438,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![false, false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -493,9 +480,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![false, false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -516,9 +501,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![true, false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -539,9 +522,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![false, true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -594,9 +575,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![true, true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -678,9 +657,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![true, true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -738,9 +715,7 @@ mod tests {
vec![(sscanf_symbol.clone(), vec![true, true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......
use std::collections::{BTreeSet, HashSet};
use std::collections::BTreeSet;
use super::*;
use crate::abstract_domain::{AbstractIdentifier, AbstractLocation};
......@@ -9,7 +9,6 @@ use crate::{
analysis::string_abstraction::{
context::symbol_calls::tests::Setup, tests::mock_project_with_intraprocedural_control_flow,
},
utils::binary::RuntimeMemoryImage,
};
#[test]
......@@ -19,9 +18,7 @@ fn test_handle_sprintf_and_snprintf_calls() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -80,9 +77,7 @@ fn test_parse_format_string_and_add_new_string_domain() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -122,9 +117,7 @@ fn test_create_string_domain_for_sprintf_snprintf() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -157,9 +150,7 @@ fn test_create_string_domain_using_data_type_approximations() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -202,9 +193,7 @@ fn test_create_string_domain_using_constants_and_sub_domains() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -368,9 +357,7 @@ fn test_fetch_constant_and_domain_for_format_specifier() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -551,9 +538,7 @@ fn test_fetch_subdomains_if_available() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -611,9 +596,7 @@ fn test_fetch_constant_domain_if_available() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......
......@@ -99,8 +99,6 @@ impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Conte
#[cfg(test)]
mod tests {
use std::collections::HashSet;
use crate::{
abstract_domain::{CharacterInclusionDomain, CharacterSet, IntervalDomain},
analysis::pointer_inference::PointerInference as PointerInferenceComputation,
......@@ -109,7 +107,6 @@ mod tests {
tests::mock_project_with_intraprocedural_control_flow,
},
intermediate_representation::{ByteSize, Variable},
utils::binary::RuntimeMemoryImage,
};
use super::*;
......@@ -121,9 +118,7 @@ mod tests {
vec![(strcat_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -157,9 +152,7 @@ mod tests {
vec![(strcat_symbol.clone(), vec![false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -210,9 +203,7 @@ mod tests {
vec![(strcat_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -234,9 +225,7 @@ mod tests {
vec![(strcat_symbol.clone(), vec![false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -263,9 +252,7 @@ mod tests {
vec![(strcat_symbol.clone(), vec![false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......
use std::collections::{HashMap, HashSet};
use std::collections::HashMap;
use std::fmt::Debug;
use petgraph::graph::NodeIndex;
......@@ -17,7 +17,7 @@ use crate::intermediate_representation::{Bitvector, ExternSymbol, Project, Sub};
use crate::{
abstract_domain::{AbstractIdentifier, AbstractLocation},
intermediate_representation::{Tid, Variable},
utils::{binary::RuntimeMemoryImage, symbol_utils::get_symbol_map},
utils::symbol_utils::get_symbol_map,
};
pub struct Setup<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String> + Debug> {
......@@ -114,9 +114,7 @@ fn test_handle_generic_symbol_calls() {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -140,9 +138,7 @@ fn test_handle_unknown_symbol_calls() {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -170,9 +166,7 @@ fn test_add_new_string_abstract_domain() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -227,9 +221,7 @@ fn test_merge_domains_from_multiple_pointer_targets() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -311,9 +303,7 @@ fn test_handle_sprintf_and_snprintf_calls_known_format_string() {
vec![(sprintf_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -348,9 +338,7 @@ fn test_handle_sprintf_and_snprintf_calls_unknown_format_string() {
vec![(sprintf_symbol.clone(), vec![false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -385,9 +373,7 @@ fn test_insert_constant_char_into_format_string() {
vec![(ExternSymbol::mock_sprintf_symbol_arm(), vec![false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -419,9 +405,7 @@ fn test_insert_constant_string_into_format_string() {
vec![(ExternSymbol::mock_sprintf_symbol_arm(), vec![false])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -450,12 +434,7 @@ fn test_handle_free() {
"func",
);
let extern_subs: HashSet<Tid> = vec![malloc_symbol.tid, free_symbol.clone().tid]
.into_iter()
.collect();
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, extern_subs);
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......
......@@ -24,8 +24,7 @@ fn test_update_def() {
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -138,9 +137,7 @@ fn test_update_jump() {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -165,9 +162,7 @@ fn test_update_return() {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......@@ -223,9 +218,7 @@ fn test_update_call_stub() {
vec![(memcpy_symbol.clone(), vec![true])],
"func",
);
let mem_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results = PointerInferenceComputation::mock(&project, &mem_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let setup: Setup<CharacterInclusionDomain> = Setup::new(&pi_results);
......
......@@ -470,7 +470,7 @@ impl ExternSymbol {
calling_convention: Some("__stdcall".to_string()),
parameters: vec![Arg::mock_register("r0", 4)],
return_values: vec![],
no_return: true,
no_return: false,
has_var_args: false,
}
}
......
......@@ -209,6 +209,9 @@ pub mod tests {
sub.term.blocks.push(block2);
project.program.term.subs.insert(sub.tid.clone(), sub);
project.program.term.entry_points.insert(Tid::new("func"));
project
.calling_conventions
.insert("__stdcall".to_string(), CallingConvention::mock());
project
}
......@@ -219,8 +222,7 @@ pub mod tests {
let runtime_memory_image = RuntimeMemoryImage::mock();
let project = mock_project();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let mut pi_results =
PointerInferenceComputation::mock(&project, &runtime_memory_image, &graph);
let mut pi_results = PointerInferenceComputation::mock(&project);
pi_results.compute();
let mut format_string_index: HashMap<String, usize> = HashMap::new();
format_string_index.insert("sprintf".to_string(), 1);
......
......@@ -418,7 +418,6 @@ impl<'a> crate::analysis::forward_interprocedural_fixpoint::Context<'a> for Cont
mod tests {
use super::*;
use crate::utils::binary::RuntimeMemoryImage;
use std::collections::HashSet;
impl<'a> Context<'a> {
pub fn mock(
......@@ -447,8 +446,7 @@ mod tests {
fn check_parameter_arg_for_taint() {
let project = Project::mock_empty();
let runtime_memory_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let pi_results = PointerInferenceComputation::mock(&project, &runtime_memory_image, &graph);
let pi_results = PointerInferenceComputation::mock(&project);
let context = Context::mock(&project, &runtime_memory_image, &pi_results);
let (mut state, _pi_state) = State::mock_with_pi_state();
......@@ -479,8 +477,7 @@ mod tests {
fn handle_generic_call() {
let project = Project::mock_empty();
let runtime_memory_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let pi_results = PointerInferenceComputation::mock(&project, &runtime_memory_image, &graph);
let pi_results = PointerInferenceComputation::mock(&project);
let context = Context::mock(&project, &runtime_memory_image, &pi_results);
let mut state = State::mock();
......@@ -501,8 +498,7 @@ mod tests {
fn update_def() {
let project = Project::mock_empty();
let runtime_memory_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let pi_results = PointerInferenceComputation::mock(&project, &runtime_memory_image, &graph);
let pi_results = PointerInferenceComputation::mock(&project);
let context = Context::mock(&project, &runtime_memory_image, &pi_results);
let (mut state, pi_state) = State::mock_with_pi_state();
state.set_pointer_inference_state(Some(pi_state));
......@@ -555,8 +551,7 @@ mod tests {
fn update_jump() {
let project = Project::mock_empty();
let runtime_memory_image = RuntimeMemoryImage::mock();
let graph = crate::analysis::graph::get_program_cfg(&project.program, HashSet::new());
let pi_results = PointerInferenceComputation::mock(&project, &runtime_memory_image, &graph);
let pi_results = PointerInferenceComputation::mock(&project);
let context = Context::mock(&project, &runtime_memory_image, &pi_results);
let (state, _pi_state) = State::mock_with_pi_state();
......
......@@ -60,14 +60,7 @@ You can find out more information about each check, including known false positi
by reading the check-specific module documentation in the [`checkers`] module.
*/
use abstract_domain::BricksDomain;
use crate::analysis::graph::Graph;
use crate::analysis::pointer_inference::PointerInference;
use crate::analysis::string_abstraction::StringAbstraction;
use crate::intermediate_representation::Project;
use crate::utils::binary::RuntimeMemoryImage;
use crate::utils::log::{CweWarning, LogMessage};
use std::collections::BTreeMap;
pub mod abstract_domain;
pub mod analysis;
......@@ -76,6 +69,15 @@ pub mod intermediate_representation;
pub mod pcode;
pub mod utils;
use abstract_domain::BricksDomain;
use analysis::function_signature::FunctionSignature;
use analysis::graph::Graph;
use analysis::pointer_inference::PointerInference;
use analysis::string_abstraction::StringAbstraction;
use intermediate_representation::Project;
use utils::binary::RuntimeMemoryImage;
use utils::log::{CweWarning, LogMessage};
mod prelude {
pub use apint::Width;
pub use serde::{Deserialize, Serialize};
......@@ -85,6 +87,7 @@ mod prelude {
pub use crate::AnalysisResults;
pub use anyhow::{anyhow, Error};
}
use prelude::*;
/// The generic function signature for the main function of a CWE module
pub type CweModuleFn =
......@@ -141,6 +144,8 @@ pub struct AnalysisResults<'a> {
pub control_flow_graph: &'a Graph<'a>,
/// A pointer to the project struct
pub project: &'a Project,
/// The results of the function signature analysis if already computed.
pub function_signatures: Option<&'a BTreeMap<Tid, FunctionSignature>>,
/// The result of the pointer inference analysis if already computed.
pub pointer_inference: Option<&'a PointerInference<'a>>,
/// The result of the string abstraction if already computed.
......@@ -160,11 +165,33 @@ impl<'a> AnalysisResults<'a> {
runtime_memory_image,
control_flow_graph,
project,
function_signatures: None,
pointer_inference: None,
string_abstraction: None,
}
}
/// Compute the function signatures for internal functions.
pub fn compute_function_signatures(
&self,
) -> (BTreeMap<Tid, FunctionSignature>, Vec<LogMessage>) {
analysis::function_signature::compute_function_signatures(
self.project,
self.control_flow_graph,
)
}
/// Create a new `AnalysisResults` struct containing the given function signature analysis results.
pub fn with_function_signatures(
self,
function_signatures: Option<&'a BTreeMap<Tid, FunctionSignature>>,
) -> AnalysisResults<'a> {
AnalysisResults {
function_signatures,
..self
}
}
/// Compute the pointer inference analysis.
/// The result gets returned, but not saved to the `AnalysisResults` struct itself.
pub fn compute_pointer_inference(
......@@ -173,9 +200,7 @@ impl<'a> AnalysisResults<'a> {
print_stats: bool,
) -> PointerInference<'a> {
crate::analysis::pointer_inference::run(
self.project,
self.runtime_memory_image,
self.control_flow_graph,
self,
serde_json::from_value(config.clone()).unwrap(),
false,
print_stats,
......@@ -183,7 +208,7 @@ impl<'a> AnalysisResults<'a> {
}
/// Create a new `AnalysisResults` struct containing the given pointer inference analysis results.
pub fn set_pointer_inference<'b: 'a>(
pub fn with_pointer_inference<'b: 'a>(
self,
pi_results: Option<&'b PointerInference<'a>>,
) -> AnalysisResults<'b> {
......@@ -212,7 +237,7 @@ impl<'a> AnalysisResults<'a> {
}
/// Create a new `AnalysisResults` struct containing the given string abstraction results.
pub fn set_string_abstraction<'b: 'a>(
pub fn with_string_abstraction<'b: 'a>(
self,
string_abstraction: Option<&'b StringAbstraction<'a, BricksDomain>>,
) -> AnalysisResults<'b> {
......@@ -222,3 +247,30 @@ impl<'a> AnalysisResults<'a> {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::analysis::graph::get_program_cfg;
use std::collections::HashSet;
impl<'a> AnalysisResults<'a> {
/// Mocks the `AnalysisResults` struct with a given project.
/// Note that the function leaks memory!
pub fn mock_from_project(project: &'a Project) -> AnalysisResults<'a> {
let extern_subs =
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 runtime_mem_image = Box::new(RuntimeMemoryImage::mock());
let runtime_mem_image: &'a RuntimeMemoryImage = Box::leak(runtime_mem_image);
let binary: &'a Vec<u8> = Box::leak(Box::new(Vec::new()));
let analysis_results = AnalysisResults::new(binary, runtime_mem_image, graph, project);
let (fn_sigs, _) = analysis_results.compute_function_signatures();
let fn_sigs: &'a BTreeMap<_, _> = Box::leak(Box::new(fn_sigs));
let analysis_results = analysis_results.with_function_signatures(Some(fn_sigs));
analysis_results
}
}
}
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