pub struct Context<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> {
    pub project: &'a Project,
    pub pointer_inference_results: &'a PointerInference<'a>,
    pub string_symbol_map: HashMap<Tid, &'a ExternSymbol>,
    pub extern_symbol_map: HashMap<Tid, &'a ExternSymbol>,
    pub format_string_index_map: HashMap<String, usize>,
    pub block_start_node_map: HashMap<(Tid, Tid), NodeIndex>,
    pub block_first_def_set: HashSet<(Tid, Tid)>,
    pub jmp_to_blk_end_node_map: HashMap<(Tid, Tid), NodeIndex>,
    /* private fields */
}
Expand description

Contains all context information needed for the string abstract fixpoint computation.

The struct also implements the interprocedural_fixpoint::Context trait to enable the fixpoint computation.

Fields§

§project: &'a Project

A reference to the Project object representing the binary

§pointer_inference_results: &'a PointerInference<'a>

A pointer to the results of the pointer inference analysis. They are used to determine the targets of pointers to memory, which in turn is used to keep track of taint on the stack or on the heap.

§string_symbol_map: HashMap<Tid, &'a ExternSymbol>

Maps the TIDs of functions that shall be treated as string extern symbols to the ExternSymbol object representing it.

§extern_symbol_map: HashMap<Tid, &'a ExternSymbol>

Maps the TIDs of functions that shall be treated as general extern symbols to the ExternSymbol object representing it.

§format_string_index_map: HashMap<String, usize>

Maps string symbols to their corresponding format string parameter index.

§block_start_node_map: HashMap<(Tid, Tid), NodeIndex>

A map to get the node index of the BlkStart node containing a given Def as the first Def of the block. The keys are of the form (Def-TID, Current-Sub-TID) to distinguish the nodes for blocks contained in more than one function.

§block_first_def_set: HashSet<(Tid, Tid)>

A set containing a given Def as the first Def of the block. The keys are of the form (Def-TID, Current-Sub-TID) to distinguish the nodes for blocks contained in more than one function.

§jmp_to_blk_end_node_map: HashMap<(Tid, Tid), NodeIndex>

A map to get the node index of the BlkEnd node containing a given Jmp. The keys are of the form (Jmp-TID, Current-Sub-TID) to distinguish the nodes for blocks contained in more than one function.

Implementations§

source§

impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Context<'a, T>

source

pub fn handle_memcpy_calls( &self, state: &State<T>, extern_symbol: &ExternSymbol ) -> State<T>

Handles the detection of string parameters to memcpy calls.

source

pub fn has_return_target( &self, extern_symbol: &ExternSymbol, pi_state: &PointerInferenceState ) -> Result<DataDomain<IntervalDomain>, Error>

Checks whether the first input parameter contains a return target.

source

pub fn has_input_target( &self, extern_symbol: &ExternSymbol, pi_state: &PointerInferenceState ) -> Result<DataDomain<IntervalDomain>, Error>

Checks whether the second input parameter contains a source target.

source

pub fn process_domains_for_memcpy_calls( &self, state: &mut State<T>, pi_state: &PointerInferenceState, return_data: DataDomain<IntervalDomain>, input_data: Option<DataDomain<IntervalDomain>> )

Processes string domains in memcpy calls on a case by case basis.

  • Case 1: Both the destination pointer domain and the source pointer domain have multiple targets. In this case all targets of the destination pointer receive Top values as it is unclear which source target correspondence to which destination target due to path insentivity.

  • Case 2: Only the destination pointer domain has multiple targets. In this case it is checked whether a string domain is tracked at the corresponding source position. If so, a new map entry is created for the string domain at all destination targets. Otherwise, a Top value is created.

  • Case 3: Both pointer domains have unique targets. In this case a potential string domain is simply copied to the destination target.

Note that it is assumed that a memcpy input is always a string as it is part of the string.h C header file.

source

pub fn process_domains_for_memcpy_calls_with_one_unique_input( &self, state: &mut State<T>, pi_state: &PointerInferenceState, input_target: &DataDomain<IntervalDomain>, relative_return_targets: &BTreeMap<AbstractIdentifier, IntervalDomain> )

Processes domains for memcpy calls where at least one of the parameters contains a unique target.

source

pub fn get_constant_target( &self, input_target: &DataDomain<IntervalDomain> ) -> Option<T>

Returns the content of a global memory target if there is some.

source

pub fn has_multiple_targets(data: &DataDomain<IntervalDomain>) -> bool

Checks whether a data domain has multiple targets.

source§

impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Context<'a, T>

source

pub fn handle_scanf_calls( &self, state: &State<T>, extern_symbol: &ExternSymbol ) -> State<T>

Handles the detection of string parameters to scanf calls. Adds new string abstract domains to the current state.

source

pub fn create_abstract_domain_entries_for_function_return_values( &self, pi_state: &PointerInferenceState, state: &mut State<T>, arg_to_value_map: HashMap<Arg, Option<String>> )

Creates string abstract domains for return values of (s)scanf calls.

source

pub fn add_constant_or_top_value_to_return_locations( state: &mut State<T>, pi_state: &PointerInferenceState, return_target: DataDomain<IntervalDomain>, value: Option<String> )

Adds constant or Top value to return location given a pointer and a potential value.

source

pub fn handle_sscanf_calls( &self, state: &State<T>, extern_symbol: &ExternSymbol ) -> State<T>

Handles calls to sscanf. If the source string is known, it is split by spaces and for each substring a string abstract domain is generated at its corresponding location.

source

pub fn source_string_mapped_to_return_locations( &self, pi_state: &PointerInferenceState, state: &mut State<T>, source_string: &DataDomain<IntervalDomain>, extern_symbol: &ExternSymbol ) -> bool

Maps the source string to the return locations of the call and returns an boolean which indicates whether the operation was successful.

source

pub fn map_source_string_parameters_to_return_arguments( &self, pi_state: &PointerInferenceState, extern_symbol: &ExternSymbol, source_string: &str ) -> Result<HashMap<Arg, Option<String>>, Error>

Maps source strings parameters to return arguments for sscanf calls.

source

pub fn filter_out_all_non_string_args( all_parameters: Vec<Arg>, return_values: Vec<String> ) -> HashMap<Arg, Option<String>>

Filters out all parameters that are not of type string.

source§

impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Context<'a, T>

source

pub fn handle_sprintf_and_snprintf_calls( &self, state: &State<T>, extern_symbol: &ExternSymbol ) -> State<T>

Handles the detection of string parameters to sprintf and snprintf calls. Is able to identify a string constant parameter and to insert it into the format string. e.g. the format string is “cat %s” and the analysis detected that the input string is a constant in memory, for instance “bash.sh”. Then the abstract string domain is constructed with the string “cat bash.sh”.

source

pub fn parse_format_string_and_add_new_string_domain( &self, state: &mut State<T>, pi_state: &PointerInferenceState, extern_symbol: &ExternSymbol, format_string_index: usize, return_pointer: &DataDomain<IntervalDomain> )

Gets the input format string, parses the input parameters and adds the generated domain to the string maps.

source

pub fn create_string_domain_for_sprintf_snprintf( &self, pi_state: &PointerInferenceState, state: &State<T>, extern_symbol: &ExternSymbol, input_format_string: String ) -> T

Creates a string domain for a s(n)printf call by considering input constants and other domains.

source

pub fn create_string_domain_using_data_type_approximations( &self, format_string: String ) -> T

Creates a domain from a format string where all specifiers are approximated according to their data type. This ensures that, if there is a long data type, that the domain is no returned as Top.

source

pub fn create_string_domain_using_constants_and_sub_domains( &self, format_string: String, var_args: &[Arg], pi_state: &PointerInferenceState, state: &State<T> ) -> T

Creates a string domain from found constants and sub domains.

source

pub fn push_format_specifier_approximation( domains: &mut Vec<T>, specifier: Match<'_> )

Creates a string domain by approximating a format specifier and pushes it to the domain vector.

source

pub fn push_constant_subsequences_before_and_between_specifiers( domains: &mut Vec<T>, format_string: &str, specifier: Match<'_>, last_specifier_end: usize, index: usize )

Creates string domains from constant subsequences that either appear at the beginning of the format string or between specifiers.

source

pub fn push_constant_suffix_if_available( domains: &mut Vec<T>, format_string: &str, last_specifier_end: usize )

Pushes a potential constant suffix to the string domain vector.

source

pub fn concat_domains(domains: &mut Vec<T>) -> T

Takes a vector of string domains and concatenates them.

source

pub fn no_specifiers(format_string: String) -> bool

Checks whether the string has no format specifiers.

source

pub fn fetch_constant_and_domain_for_format_specifier( &self, arg: &Arg, specifier: String, pi_state: &PointerInferenceState, state: &State<T> ) -> T

Tries to fetch a constant or sub domain for the format specifier. If no data is available, it approximates the sub domain corresponding to the characters that can be contained in the data type.

source

pub fn trim_format_specifier(specifier: String) -> String

Removes the ‘%’ character and any size number from a format specifier.

source

pub fn fetch_subdomains_if_available( data: &DataDomain<IntervalDomain>, state: &State<T>, pi_state: &PointerInferenceState, arg: &Arg, constant_domain: Option<T> ) -> Option<T>

Fetches subdomains if they are available for a pointer domain and merges a potential constant domain into the result.

source

pub fn fetch_constant_domain_if_available( &self, data: &DataDomain<IntervalDomain>, arg: &Arg ) -> Option<T>

Takes a data domain and tries to get a constant value.

source§

impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Context<'a, T>

source

pub fn handle_strcat_and_strncat_calls( &self, state: &State<T>, extern_symbol: &ExternSymbol ) -> State<T>

Handles the resulting string domain from strcat and strncat calls. The symbol call returns the pointer to the destination string in its return register.

source

pub fn process_second_input_domain( &self, state: &State<T>, extern_symbol: &ExternSymbol, pi_state: &PointerInferenceState ) -> T

Processes the contents of the second input parameter.

source§

impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Context<'a, T>

source

pub fn handle_generic_symbol_calls( &self, extern_symbol: &ExternSymbol, state: &State<T> ) -> State<T>

Handles generic symbol calls by deleting all non callee saved pointer entries.

source

pub fn handle_unknown_symbol_calls(&self, state: &mut State<T>)

Handles calls to external symbols for which no ExternSymbol object is known.

source

pub fn handle_string_symbol_calls( &self, extern_symbol: &ExternSymbol, state: &State<T> ) -> State<T>

The output of a string symbol is added to the map of abstract strings. If the symbol returns a format string, the string is approximated as good as possible by checking the input parameters.

source

pub fn add_new_string_abstract_domain( state: &mut State<T>, pi_state: &PointerInferenceState, pointer: &BTreeMap<AbstractIdentifier, IntervalDomain>, domain_input_string: T )

Takes the pointer target if there is only one and checks whether the target is inside the current stack frame. If so, the string domain is added to the analysis.

source

pub fn re_format_specifier() -> Regex

Regex that filters format specifier from a format string.

source

pub fn merge_domains_from_multiple_pointer_targets( state: &State<T>, pi_state: &PointerInferenceState, pointer: &BTreeMap<AbstractIdentifier, IntervalDomain> ) -> T

Merges domains from multiple pointer targets. The merged domain serves as input to a format string. If one of the targets does not contain a domain or the offset of a stack target cannot be parsed, a Top value is returned as no assumption can be made about the input.

source

pub fn approximate_string_domain_from_datatype(specifier: String) -> T

Calls the appropriate data type approximator.

source

pub fn get_constant_integer_domain(constant: Bitvector) -> Option<T>

Inserts an integer constant into the format string.

source

pub fn get_constant_char_domain(&self, constant: Bitvector) -> Option<T>

Inserts a char constant into the format string.

source

pub fn parse_bitvec_to_char(char_code: Bitvector) -> Option<char>

Parses a bitvector to a char if possible.

source

pub fn get_constant_string_domain(&self, constant: Bitvector) -> Option<T>

Inserts a string constant into the format string.

source

pub fn handle_free( &self, state: &State<T>, extern_symbol: &ExternSymbol ) -> State<T>

Deletes string entries in the heap to string map if the corresponding pointer is used to free memory space.

source§

impl<'a, T: AbstractDomain + HasTop + Eq + From<String> + DomainInsertion> Context<'a, T>

source

pub fn new( project: &'a Project, pointer_inference_results: &'a PointerInferenceComputation<'a>, config: Config ) -> Context<'a, T>

Create a new context object for a given project.

Trait Implementations§

source§

impl<'a, T: AbstractDomain + DomainInsertion + HasTop + Eq + From<String>> Context<'a> for Context<'a, T>

source§

fn get_graph(&self) -> &Graph<'a>

Get the underlying graph on which the analysis operates.

source§

fn merge(&self, state1: &Self::Value, state2: &Self::Value) -> State<T>

Merge two state values.

§

type Value = State<T>

The type of the values that are assigned to nodes during the fixpoint computation.
source§

fn update_def(&self, state: &State<T>, def: &Term<Def>) -> Option<State<T>>

Transition function for Def terms. The transition function for a basic block is computed by iteratively applying this function to the starting value for each Def term in the basic block. The iteration short-circuits and returns None if update_def returns None at any point.
source§

fn update_jump( &self, state: &State<T>, _jump: &Term<Jmp>, _untaken_conditional: Option<&Term<Jmp>>, _target: &Term<Blk> ) -> Option<State<T>>

Transition function for (conditional and unconditional) Jmp terms.
source§

fn update_call( &self, _state: &State<T>, _call: &Term<Jmp>, _target: &Node<'_>, _calling_convention: &Option<String> ) -> Option<State<T>>

Transition function for in-program calls.
source§

fn update_return( &self, _state: Option<&State<T>>, state_before_call: Option<&State<T>>, _call_term: &Term<Jmp>, _return_term: &Term<Jmp>, _calling_convention: &Option<String> ) -> Option<State<T>>

Transition function for return instructions. Has access to the value at the callsite corresponding to the return edge. This way one can recover caller-specific information on return from a function.
source§

fn update_call_stub( &self, state: &State<T>, call: &Term<Jmp> ) -> Option<State<T>>

Transition function for calls to functions not contained in the binary. The corresponding edge goes from the callsite to the returned-to block.
source§

fn specialize_conditional( &self, state: &State<T>, _condition: &Expression, _block_before_condition: &Term<Blk>, _is_true: bool ) -> Option<State<T>>

This function is used to refine the value using the information on which branch was taken on a conditional jump.

Auto Trait Implementations§

§

impl<'a, T> RefUnwindSafe for Context<'a, T>
where T: RefUnwindSafe,

§

impl<'a, T> Send for Context<'a, T>
where T: Send,

§

impl<'a, T> Sync for Context<'a, T>
where T: Sync,

§

impl<'a, T> Unpin for Context<'a, T>
where T: Unpin,

§

impl<'a, T> UnwindSafe for Context<'a, T>
where T: UnwindSafe,

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.