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