Unverified Commit b571c3eb by Melvin Klimke Committed by GitHub

Error Handling for Parameter Parsing (#193)

parent 2de59afc
......@@ -74,30 +74,36 @@ impl<'a> Context<'a> {
.pointer_inference_results
.get_node_value(call_source_node)
{
let parameters = arguments::get_variable_number_parameters(
if let Ok(parameters) = arguments::get_variable_number_parameters(
self.project,
pi_state,
user_input_symbol,
&self.symbol_maps.format_string_index,
self.runtime_memory_image,
);
if !parameters.is_empty() {
match user_input_symbol.name.as_str() {
"scanf" | "__isoc99_scanf" => {
self.process_scanf(call_source_node, &mut new_state, pi_state, parameters)
}
"sscanf" | "__isoc99_sscanf" => {
let source_string_register = user_input_symbol.parameters.get(0).unwrap();
self.process_sscanf(
) {
if !parameters.is_empty() {
match user_input_symbol.name.as_str() {
"scanf" | "__isoc99_scanf" => self.process_scanf(
call_source_node,
&mut new_state,
pi_state,
parameters,
source_string_register,
)
),
"sscanf" | "__isoc99_sscanf" => {
let source_string_register =
user_input_symbol.parameters.get(0).unwrap();
self.process_sscanf(
&mut new_state,
pi_state,
parameters,
source_string_register,
)
}
_ => panic!("Invalid user input symbol."),
}
_ => panic!("Invalid user input symbol."),
}
}
// TODO: Log errors that came up during the parameter parsing.
}
new_state
}
......@@ -222,13 +228,18 @@ impl<'a> Context<'a> {
if self.is_relevant_string_function_call(string_symbol, pi_state, &mut new_state) {
let mut parameters = string_symbol.parameters.clone();
if string_symbol.has_var_args {
parameters = arguments::get_variable_number_parameters(
if let Ok(args) = arguments::get_variable_number_parameters(
self.project,
pi_state,
string_symbol,
&self.symbol_maps.format_string_index,
self.runtime_memory_image,
);
) {
parameters = args;
} else {
// TODO: Log errors that came up during the parameter parsing.
parameters = vec![]
}
}
self.taint_function_parameters(&mut new_state, pi_state, parameters);
}
......
......@@ -2,6 +2,8 @@
use std::collections::HashMap;
use crate::prelude::*;
use regex::Regex;
use crate::{
......@@ -33,40 +35,46 @@ pub fn get_input_format_string(
format_string_index: usize,
stack_pointer_register: &Variable,
runtime_memory_image: &RuntimeMemoryImage,
) -> String {
) -> Result<String, Error> {
if let Some(format_string) = extern_symbol.parameters.get(format_string_index) {
if let Ok(address) = pi_state.eval_parameter_arg(
if let Ok(DataDomain::Value(address)) = pi_state.eval_parameter_arg(
format_string,
&stack_pointer_register,
runtime_memory_image,
) {
parse_format_string_destination_and_return_content(address, runtime_memory_image)
} else {
panic!("Could not parse target address of format string pointer.");
return parse_format_string_destination_and_return_content(
address,
runtime_memory_image,
);
}
} else {
panic!(
"No format string parameter at specified index {} for function {}",
format_string_index, extern_symbol.name
);
return Err(anyhow!("Format string not in global memory."));
}
Err(anyhow!(
"No format string parameter at specified index {} for function {}",
format_string_index,
extern_symbol.name
))
}
/// Parses the destiniation address of the format string.
/// It checks whether the address points to another pointer in memory.
/// If so, it will use the target address of that pointer read the format string from memory.
pub fn parse_format_string_destination_and_return_content(
address: DataDomain<IntervalDomain>,
address: IntervalDomain,
runtime_memory_image: &RuntimeMemoryImage,
) -> String {
) -> Result<String, Error> {
if let Ok(address_vector) = address.try_to_bitvec() {
match runtime_memory_image.read_string_until_null_terminator(&address_vector) {
Ok(format_string) => format_string.to_string(),
Err(e) => panic!("{}", e),
}
} else {
panic!("Could not translate format string address to bitvector.");
return match runtime_memory_image.read_string_until_null_terminator(&address_vector) {
Ok(format_string) => Ok(format_string.to_string()),
Err(e) => Err(anyhow!("{}", e)),
};
}
Err(anyhow!(
"Could not translate format string address to bitvector."
))
}
/// Parses the format string parameters using a regex, determines their data types,
......@@ -115,30 +123,39 @@ pub fn get_variable_number_parameters(
extern_symbol: &ExternSymbol,
format_string_index_map: &HashMap<String, usize>,
runtime_memory_image: &RuntimeMemoryImage,
) -> Vec<Arg> {
) -> Result<Vec<Arg>, Error> {
let format_string_index = match format_string_index_map.get(&extern_symbol.name) {
Some(index) => *index,
None => panic!("External Symbol does not contain a format string parameter."),
};
let format_string = get_input_format_string(
let format_string_results = get_input_format_string(
pi_state,
extern_symbol,
format_string_index,
&project.stack_pointer_register,
runtime_memory_image,
);
let parameters =
parse_format_string_parameters(format_string.as_str(), &project.datatype_properties);
if parameters.iter().any(|(specifier, _)| is_string(specifier)) {
return calculate_parameter_locations(
project,
parameters,
extern_symbol.get_calling_convention(project),
format_string_index,
);
if let Ok(format_string) = format_string_results {
let parameters =
parse_format_string_parameters(format_string.as_str(), &project.datatype_properties);
if parameters.iter().any(|(specifier, _)| is_string(specifier)) {
return Ok(calculate_parameter_locations(
project,
parameters,
extern_symbol.get_calling_convention(project),
format_string_index,
));
}
return Ok(vec![]);
}
vec![]
Err(anyhow!(
"Could not parse variable parameters: {}",
format_string_results.unwrap_err()
))
}
/// Calculates the register and stack positions of format string parameters.
......
......@@ -43,6 +43,7 @@ fn test_get_variable_number_parameters() {
&format_string_index_map,
&mem_image,
)
.unwrap()
);
output.push(Arg::Stack {
......@@ -65,6 +66,7 @@ fn test_get_variable_number_parameters() {
&format_string_index_map,
&mem_image,
)
.unwrap()
);
}
......@@ -89,6 +91,7 @@ fn test_get_input_format_string() {
&Variable::mock("RSP", 8 as u64),
&mem_image
)
.unwrap()
);
}
......@@ -96,14 +99,11 @@ fn test_get_input_format_string() {
fn test_parse_format_string_destination_and_return_content() {
let mem_image = RuntimeMemoryImage::mock();
let string_address_vector = Bitvector::from_str_radix(16, "3002").unwrap();
let string_address = DataDomain::Value(IntervalDomain::new(
string_address_vector.clone(),
string_address_vector,
));
let string_address = IntervalDomain::new(string_address_vector.clone(), string_address_vector);
assert_eq!(
"Hello World",
parse_format_string_destination_and_return_content(string_address, &mem_image)
parse_format_string_destination_and_return_content(string_address, &mem_image).unwrap()
);
}
......
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