Skip to content

Commit

Permalink
Fix make codestyle-check
Browse files Browse the repository at this point in the history
  • Loading branch information
Valentin Obst committed Aug 20, 2024
1 parent 6dbecae commit 31625be
Show file tree
Hide file tree
Showing 42 changed files with 738 additions and 502 deletions.
22 changes: 13 additions & 9 deletions src/cwe_checker_lib/src/abstract_domain/bricks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,29 @@
//!
//! The BricksDomain contains a sorted list of normalized BrickDomains.
//! It represents the composition of a string through sub sequences.
//! When a string is assigned to the BricksDomain, it is defined as a single sequence bricks
//! which occurs at least and at most one time which is represented by a min and max value in the
//! When a string is assigned to the BricksDomain, it is defined as a single
//! sequence bricks which occurs at least and at most one time which is
//! represented by a min and max value in the
//! BrickDomain. e.g. "cwe" => \[\[{"cwe"}\]^{1,1}\]
//!
//! If two string are concatenated, their brick sequences are concatenated.
//! If two string are concatenated, their brick sequences are concatenated:
//! e.g. B1 = \[\[{"a"}\]^{1,1}\], B2 = \[\[{"b"}\]^{1,1}\] => B_new = \[\[{"a"}\]^{1,1}, \[{"b"}\]^{1,1}\]
//!
//! A set of strings can be built from multiple configurations of bricks
//! A set of strings can be built from multiple configurations of bricks:
//! e.g. \[{"abc"}\]^{1,1} <=> \[{"a"}\]^{1,1}\[{"b"}\]^{1,1}\[{"c"}\]^{1,1}
//!
//! Introducing a normalized form \[T\]^{1,1} or \[T\]^{0, max>0}
//! will keep string representations unambiguous.
//!
//! Widening is applied for merges, so that the domains do not become too big.
//! Certain thresholds are defined which cause the domains to be widened if exceeded.
//! These thresholds are:
//! - the *interval threshold* which overapproximates the number of times string sequences can occur in a brick.
//! - the *sequence threshold* which overapproximates the number of string sequences in a brick by forcing a *Top* value.
//! - the *length threshold* which overapproximates the number of bricks in the BricksDomain and forces a *Top* value.
//! Certain thresholds are defined which cause the domains to be widened if
//! exceeded. These thresholds are:
//! - The *interval threshold* which overapproximates the number of times
//! string sequences can occur in a brick.
//! - The *sequence threshold* which overapproximates the number of string
//! sequences in a brick by forcing a *Top* value.
//! - The *length threshold* which overapproximates the number of bricks in
//! the BricksDomain and forces a *Top* value.

use std::{collections::BTreeSet, fmt};

Expand Down
18 changes: 13 additions & 5 deletions src/cwe_checker_lib/src/abstract_domain/bricks/widening.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
//! This module implements the widening operator for the BrickDomain and BricksDomain.
//! This module implements the widening operator for the BrickDomain and
//! BricksDomain.
//!
//! The exact widening procedure depends on three constants.
//! - The *interval threshold* overapproximates the number of times string sequences can occur in a brick.
//! - The *sequence threshold* overapproximates the number of string sequences in a brick by forcing a *Top* value.
//! - The *length threshold* overapproximates the number of bricks in the BricksDomain and forces a *Top* value.
//! A merge is processed without widening when none of the thresholds are exceeded.
//!
//! - The *interval threshold* overapproximates the number of times string
//! sequences can occur in a brick.
//! - The *sequence threshold* overapproximates the number of string sequences
//! in a brick by forcing a *Top* value.
//! - The *length threshold* overapproximates the number of bricks in the
//! BricksDomain and forces a *Top* value.
//!
//! A merge is processed without widening when none of the thresholds are
//! exceeded.

use std::{
cmp::{
Expand Down
27 changes: 18 additions & 9 deletions src/cwe_checker_lib/src/abstract_domain/character_inclusion.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
//! This module contains the Character Inclusion Domain (CI).
//!
//! This domain considers the characters of a string and distinguishes
//! between two scenarios which are stored in different HashSets.
//! between two scenarios which are stored in different HashSets:
//!
//! - The first set contains characters that are certainly contained in
//! the string.
//! - The second set contains characters that may be in the string.
//!
//! This distinction is made when two CI domains merge.
//! Furthermore, the CI domain does not preserve information about the order of characters.
//!
//! Furthermore, the CI domain does not preserve information about the order of
//! characters.
//!
//! The *Top* value of the CI domain stands for an empty set of certainly
//! contained characters and the whole alphabet of allowed characters for the possibly contained characters.
//! contained characters and the whole alphabet of allowed characters for the
//! possibly contained characters.
//!
//! The following presents an example which shows how the CI domain works:
//! 1. When a string is assigned to the CI domain its unique characters are stored in both
//! sets. e.g. "Hello, World!" => ({H,e,l,o,',',' ',W,o,r,d}, {H,e,l,o,',',' ',W,o,r,d})
//! 2. When two strings are concatenated, the union of the two sets of the two domains is taken.
//! e.g. "Hello, " + "World" => ({H,e,l,o,',',' '} v {W,o,r,d}, {H,e,l,o,',',' '} v {W,o,r,d})
//! 3. When two domains are merged, the intersection of the certain sets and the union of possible sets are taken.
//! e.g. ({H,e,l,o,',',' '}, {H,e,l,o,',',' '}) v ({W,o,r,l,d}, {W,o,r,l,d}) => ({l,o}, {H,e,l,o,',',' ',W,o,r,d})
//!
//! 1. When a string is assigned to the CI domain its unique characters are
//! stored in both sets. e.g.
//! "Hello, World!" => ({H,e,l,o,',',' ',W,o,r,d}, {H,e,l,o,',',' ',W,o,r,d})
//! 2. When two strings are concatenated, the union of the two sets of the two
//! domains is taken. e.g.
//! "Hello, " + "World" => ({H,e,l,o,',',' '} v {W,o,r,d}, {H,e,l,o,',',' '} v {W,o,r,d})
//! 3. When two domains are merged, the intersection of the certain sets and
//! the union of possible sets are taken, e.g.
//! ({H,e,l,o,',',' '}, {H,e,l,o,',',' '}) v ({W,o,r,l,d}, {W,o,r,l,d}) => ({l,o}, {H,e,l,o,',',' ',W,o,r,d})

use std::{collections::BTreeSet, fmt};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,13 @@ impl<T: SpecializeByConditional + RegisterDomain> SpecializeByConditional for Da
/// Compute the intersetion of two DataDomains.
///
/// Note that this implementation is unsound for several reasons:
/// - For example, it assumes that two different relative values cannot intersect.
/// But that is not true if their offfsets are big enough
/// or if the relative values do in fact reference the same object despite having different identifiers.
/// - If intersecting relative values with absolute values we represent the result with the absolute values.
/// But depending on the use-case an approximation by the relative values could be more precise.
/// - For example, it assumes that two different relative values cannot
/// intersect. But that is not true if their offfsets are big enough
/// or if the relative values do in fact reference the same object despite
/// having different identifiers.
/// - If intersecting relative values with absolute values we represent the
/// result with the absolute values. But depending on the use-case an
/// approximation by the relative values could be more precise.
fn intersect(self, other: &Self) -> Result<Self, Error> {
let mut result = match (self.contains_top_values, other.contains_top_values) {
// If only one input value contains top elements, then the other input is the best approximation for the intersection.
Expand Down
57 changes: 35 additions & 22 deletions src/cwe_checker_lib/src/abstract_domain/domain_map.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Types and traits for defining [`AbstractDomain`]s that are spaces of
//! functions onto [`AbstractDomain`]s.
use std::collections::BTreeMap;
use std::marker::PhantomData;
use std::ops::Deref;
Expand All @@ -6,19 +8,21 @@ use std::sync::Arc;

use super::*;

/// A `DomainMap<Key, Value, MapMergeStrategy>` is a wrapper type around a `BTreeMap<Key, Value>
/// where the `Value` type is an abstract domain and the map itself is also an abstract domain.
/// A `DomainMap<Key, Value, MapMergeStrategy>` is a wrapper type around a
/// `BTreeMap<Key, Value> where the `Value` type is an abstract domain and the
/// map itself is also an abstract domain. This captures the fact that the set
/// of functions from any set into a poset form a poset themselves.
///
/// For example, a map from registers to an abstract domain representing the contained values
/// can be represented by a `DomainMap`.
/// For example, a map from registers to an abstract domain representing the
/// contained values can be represented by a `DomainMap`.
///
/// A `DomainMap` has two main advantages over a regular `BTreeMap`:
/// * The map itself is wrapped into an `Arc<..>` to enable cheap cloning of `DomainMaps`.
/// * The `DomainMap` automatically implements the [`AbstractDomain`] trait
/// according to the provided [`MapMergeStrategy`] used for merging two maps.
/// according to the provided [`MapMergeStrategy`] used for merging two maps.
///
/// Since a `DomainMap` implements the `Deref` and `DerefMut` traits with target the inner `BTreeMap`,
/// it can be used just like a `BTreeMap`.
/// Since a `DomainMap` implements the `Deref` and `DerefMut` traits with target
/// the inner `BTreeMap`, it can be used just like a `BTreeMap`.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct DomainMap<K, V, S>
where
Expand Down Expand Up @@ -75,7 +79,8 @@ where
V: AbstractDomain,
S: MapMergeStrategy<K, V>,
{
/// Generate a new `DomainMap` from an iterator over the key-value pairs that it should contain.
/// Generate a new `DomainMap` from an iterator over the key-value pairs
/// that it should contain.
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = (K, V)>,
Expand All @@ -93,7 +98,8 @@ where
V: AbstractDomain,
S: MapMergeStrategy<K, V> + Clone + Eq,
{
/// Merge two `DomainMaps` according to the [`MapMergeStrategy`] of the `DomainMap`.
/// Merge two `DomainMaps` according to the [`MapMergeStrategy`] of the
/// `DomainMap`.
fn merge(&self, other: &Self) -> Self {
if self == other {
self.clone()
Expand Down Expand Up @@ -149,7 +155,8 @@ where
}
}

/// A `MapMergeStrategy` determines how the merge-method for a [`DomainMap`] works.
/// A `MapMergeStrategy` determines how the merge-method for a [`DomainMap`]
/// works.
///
/// The possible strategies are:
/// * [`UnionMergeStrategy`]
Expand All @@ -175,13 +182,15 @@ pub trait MapMergeStrategy<K: Ord + Clone, V: AbstractDomain> {
fn merge_map_with(map: &mut BTreeMap<K, V>, other: &BTreeMap<K, V>);
}

/// A [`MapMergeStrategy`] where key-value pairs whose key is only present in one input map
/// are added to the merged map.
/// `Top` values and their corresponding keys are also preserved in the merged map.
/// A [`MapMergeStrategy`] where key-value pairs whose key is only present in
/// one input map are added to the merged map.
///
/// The strategy is meant to be used for maps
/// where the values associated to keys not present in the map
/// have an implicit bottom value of the value abstract domain associated to them.
/// `Top` values and their corresponding keys are also preserved in the merged
/// map.
///
/// The strategy is meant to be used for maps where the values associated to
/// keys not present in the map have an implicit bottom value of the value
/// abstract domain associated to them.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct UnionMergeStrategy {
_private: (), // Marker to prevent instantiation
Expand Down Expand Up @@ -228,13 +237,17 @@ impl<K: Ord + Clone, V: AbstractDomain> MapMergeStrategy<K, V> for IntersectMerg
}
}

/// A [`MapMergeStrategy`] where for every key that only occurs in one input map of the merge function
/// the corresponding value is merged with `Top` before being added to the merged map.
/// Furthermore, keys whose values are merged to the `Top` value are removed from the merged map.
/// A [`MapMergeStrategy`] where for every key that only occurs in one input map
/// of the merge function the corresponding value is merged with `Top` before
/// being added to the merged map.
///
/// Furthermore, keys whose values are merged to the `Top` value are removed
/// from the merged map.
///
/// The strategy is an alternative to the [`IntersectMergeStrategy`]
/// in cases where the `Top` value of the value domain is not a maximal element of the abstract domain
/// and should instead be interpreted as a default element assigned to all keys not present in a domain map.
/// The strategy is an alternative to the [`IntersectMergeStrategy`] in cases
/// where the `Top` value of the value domain is not a maximal element of the
/// abstract domain and should instead be interpreted as a default element
/// assigned to all keys not present in a domain map.
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct MergeTopStrategy {
_private: (), // Marker to prevent instantiation
Expand Down
2 changes: 1 addition & 1 deletion src/cwe_checker_lib/src/analysis/function_signature/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use crate::analysis::graph::*;
use crate::analysis::interprocedural_fixpoint_generic::NodeValue;
use crate::intermediate_representation::*;
use crate::prelude::*;
use crate::utils::log::{WithLogs, LogMessage};
use crate::utils::log::{LogMessage, WithLogs};
use std::collections::BTreeMap;

mod context;
Expand Down
42 changes: 26 additions & 16 deletions src/cwe_checker_lib/src/analysis/function_signature/stubs.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! This module contains stubs for frequently used LibC-symbols
//! as well as helper functions for handling the effects of calls to these functions.
//! Stubs for frequently used LibC-symbols.
//!
//! This module contains stubs for frequently used LibC-symbols as well as
//! helper functions for handling the effects of calls to these functions.

use super::State;
use crate::abstract_domain::AbstractDomain;
Expand All @@ -13,10 +15,12 @@ use crate::{
};
use std::collections::BTreeMap;

/// Returns a map that maps the names of known extern functions to the access patterns for their parameters.
/// Returns a map that maps the names of known extern functions to the access
/// patterns for their parameters.
///
/// The access patterns are ordered in the same order as the parameters
/// (i.e. the first access pattern corresponds to the first parameter and so on).
/// (i.e. the first access pattern corresponds to the first parameter and so
/// on).
pub fn generate_param_access_stubs() -> BTreeMap<&'static str, Vec<AccessPattern>> {
let read = || AccessPattern::new().with_read_flag();
let deref = || {
Expand Down Expand Up @@ -125,12 +129,15 @@ pub fn generate_param_access_stubs() -> BTreeMap<&'static str, Vec<AccessPattern
])
}

/// Return a map that maps names of stubbed variadic symbols to a tuple consisting of:
/// - the index of the format string parameter of the symbol
/// - the access pattern that the called symbols uses to access its variadic parameters.
/// Note that the access pattern may vary between variadic parameters,
/// e.g. some parameters may only be read and not derefenced by a call to `printf`.
/// But we still approximate all accesses by the the maximal possible access to these parameters.
/// Return a map that maps names of stubbed variadic symbols to a tuple
/// consisting of:
///
/// - The index of the format string parameter of the symbol.
/// - The access pattern that the called symbols uses to access its variadic
/// parameters. Note that the access pattern may vary between variadic
/// parameters, e.g. some parameters may only be read and not derefenced by a
/// call to `printf`. But we still approximate all accesses by the the maximal
/// possible access to these parameters.
pub fn get_stubbed_variadic_symbols() -> BTreeMap<&'static str, (usize, AccessPattern)> {
let deref = || {
AccessPattern::new()
Expand All @@ -152,13 +159,16 @@ pub fn get_stubbed_variadic_symbols() -> BTreeMap<&'static str, (usize, AccessPa
])
}

/// Compute the return value of a call to a known extern symbol from the given state.
/// Compute the return value of a call to a known extern symbol from the given
/// state.
///
/// Note that this function needs to be called before non-callee-saved registers are cleared from the state,
/// since the return value is usually computed out of the parameter values.
/// Note that this function needs to be called before non-callee-saved registers
/// are cleared from the state, since the return value is usually computed out
/// of the parameter values.
///
/// This function should only be called for symbols contained in the list returned by [generate_param_access_stubs],
/// since it assumes untracked return values (e.g. integers or void) for all not explicitly handled symbols.
/// This function should only be called for symbols contained in the list
/// returned by [generate_param_access_stubs], since it assumes untracked return
/// values (e.g. integers or void) for all not explicitly handled symbols.
pub fn compute_return_value_for_stubbed_function(
project: &Project,
state: &mut State,
Expand Down Expand Up @@ -187,8 +197,8 @@ pub fn compute_return_value_for_stubbed_function(
}
}

/// Helper functions for computing return values for extern symbol calls.
pub mod return_value_stubs {
//! Helper functions for computing return values for extern symbol calls.
use crate::{abstract_domain::AbstractIdentifier, intermediate_representation::Arg};

use super::*;
Expand Down
Loading

0 comments on commit 31625be

Please sign in to comment.