pub struct DataDomain<T: RegisterDomain> { /* private fields */ }
Expand description

An abstract domain representing a set of base values plus offsets or an absolute value (or both).

The base values are represented as abstract IDs, i.e. they are treated as variables with unknown absolute value, e.g. the returned pointer by malloc. For each base value the offset is given by an abstract domain T, which should specialize in representing absolute values (e.g. an interval domain). Note that the domain assumes pointer semantics for these values. That means if one applies operations to the domain that are not used in pointer arithmetics, the abstract ID of the base value might be removed from the domain.

If the domain also represents absolute values, then the values are given by a single instance of the abstract domain T.

The domain also contains a flag to indicate that it includes Top values, i.e. values of fully unknown origin and offset.

Implementations§

source§

impl<T: RegisterDomain> DataDomain<T>

source

pub fn add_offset(&self, offset: &T) -> Self

Add offset to all contained absolute and relative values of self and return the result.

source

pub fn subtract_offset(&self, offset: &T) -> Self

Subtract offset from all contained absolute and relative values of self and return the result.

source§

impl<T: RegisterDomain> DataDomain<T>

source

pub fn is_empty(&self) -> bool

Returns true if the domain does not represent any value.

The meaning of an empty value depends on the usage of the domain. E.g. it may indicate an impossible runtime state of a program in one analysis or simply no value of interest in another analysis.

An empty value represents the bottom value in the partial order of the domain.

source

pub fn new_empty(size: ByteSize) -> Self

Return a new empty value with the given bytesize.

source

pub fn replace_abstract_id( &mut self, old_id: &AbstractIdentifier, new_id: &AbstractIdentifier, offset_adjustment: &T )

For pointer values replace an abstract identifier with another one and add the offset_adjustment to the pointer offset. This is needed to adjust stack pointer on call and return instructions.

source

pub fn replace_all_ids( &mut self, replacement_map: &BTreeMap<AbstractIdentifier, Self> )

Replace all abstract IDs in self with the corresponding values given by the replacement_map.

For IDs without a replacement value the contains_top_values flag will be set.

source

pub fn referenced_ids(&self) -> impl Iterator<Item = &AbstractIdentifier>

Return an iterator over all referenced abstract IDs.

source

pub fn get_relative_values(&self) -> &BTreeMap<AbstractIdentifier, T>

Return the relative values contained in the domain.

source

pub fn set_relative_values( &mut self, relative_values: BTreeMap<AbstractIdentifier, T> )

Replace the map of relative values with the given one.

source

pub fn get_absolute_value(&self) -> Option<&T>

Return the absolute value contained in the domain if present

source

pub fn set_absolute_value(&mut self, value: Option<T>)

Replace the absolute value contained in the domain with the given one. A value of None means that the domain does not contain an absolute value.

source

pub fn contains_top(&self) -> bool

Returns true if the domain contains Top values, i.e. values for which neither a value nor an abstract identifier is known.

Note that the DataDomain itself has no maximal value, i.e. this does not indicate a Top value of the abstract domain.

source

pub fn set_contains_top_flag(&mut self)

Indicate that the domain may contain Top values in addition to the contained absolute and relative values.

This does not remove absolute or relative value information from the domain.

source

pub fn unset_contains_top_flag(&mut self)

Indicate that the domain does not contain any Top values in addition to the contained absolute and relative values.

source

pub fn from_target(id: AbstractIdentifier, offset: T) -> Self

Return a new value representing a variable plus an offset, where the variable is represented by the given abstract ID.

source

pub fn remove_ids(&mut self, ids_to_remove: &BTreeSet<AbstractIdentifier>)

Remove all provided IDs from the list of relative values.

source

pub fn get_if_absolute_value(&self) -> Option<&T>

Return the contained absolute value only if self contains no other (relative or Top) values.

source

pub fn get_if_unique_target(&self) -> Option<(&AbstractIdentifier, &T)>

Return the target ID and offset of the contained relative value if self contains exactly one relative value and no absolute or Top values.

source§

impl<T: RegisterDomain + Display> DataDomain<T>

source

pub fn to_json_compact(&self) -> Value

Get a more compact json-representation of the data domain. Intended for pretty printing, not useable for serialization/deserialization.

Trait Implementations§

source§

impl<T: RegisterDomain> AbstractDomain for DataDomain<T>

source§

fn is_top(&self) -> bool

Return whether the element represents a top element or not.

Note that DataDomain technically does not have a Top element with respect to the partial order. Instead a Top element here represents a non-empty value for which nothing is known about the contained values.

source§

fn merge(&self, other: &Self) -> Self

Returns an upper bound (with respect to the partial order on the domain) for the two inputs self and other.
source§

fn merge_with(&mut self, other: &Self) -> &mut Self

Returns an upper bound (with respect to the partial order on the domain) for the two inputs self and other. Read more
source§

impl<T: RegisterDomain> Add for DataDomain<T>

§

type Output = DataDomain<T>

The resulting type after applying the + operator.
source§

fn add(self, rhs: Self) -> Self

Performs the + operation. Read more
source§

impl<T: Clone + RegisterDomain> Clone for DataDomain<T>

source§

fn clone(&self) -> DataDomain<T>

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Debug + RegisterDomain> Debug for DataDomain<T>

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<'de, T> Deserialize<'de> for DataDomain<T>
where T: Deserialize<'de> + RegisterDomain,

source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
source§

impl<T: RegisterDomain + From<Bitvector>> From<ApInt> for DataDomain<T>

source§

fn from(bitvector: Bitvector) -> Self

Converts to this type from the input type.
source§

impl<T: RegisterDomain> From<T> for DataDomain<T>

source§

fn from(value: T) -> Self

Converts to this type from the input type.
source§

impl<T: RegisterDomain> HasTop for DataDomain<T>

source§

fn top(&self) -> Self

Generate a new Top element with the same bytesize as self.

source§

impl<'a> HasVsaResult<DataDomain<IntervalDomain>> for Context<'a>

source§

fn vsa_result(&self) -> &impl VsaResult<ValueDomain = PiData>

Converts a reference to Self into a reference to a type that implements VsaResult with ValueDomain T.
source§

impl<T: Hash + RegisterDomain> Hash for DataDomain<T>

source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
source§

impl<T: PartialEq + RegisterDomain> PartialEq for DataDomain<T>

source§

fn eq(&self, other: &DataDomain<T>) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T: RegisterDomain> RegisterDomain for DataDomain<T>

source§

fn bin_op(&self, op: BinOpType, rhs: &Self) -> Self

Compute the (abstract) result of a binary operation

source§

fn un_op(&self, op: UnOpType) -> Self

Compute the (abstract) result of a unary operation

source§

fn subpiece(&self, low_byte: ByteSize, size: ByteSize) -> Self

extract a sub-bitvector

source§

fn cast(&self, kind: CastOpType, width: ByteSize) -> Self

Cast a bitvector using the given cast type

source§

fn bin_op_bytesize(&self, op: BinOpType, rhs: &Self) -> ByteSize

Return the bytesize of the result of the given binary operation. Has a generic implementation that should not be overwritten!
source§

impl<T> Serialize for DataDomain<T>

source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more
source§

impl<T: RegisterDomain> SizedDomain for DataDomain<T>

source§

fn bytesize(&self) -> ByteSize

Return the bytesize of self.

source§

fn new_top(bytesize: ByteSize) -> Self

Return a new Top element with the given bytesize.

Note that DataDomain technically does not have a Top element with respect to the partial order. Instead a Top element here represents a non-empty value for which nothing is known about the contained values.

source§

impl<T: SpecializeByConditional + RegisterDomain> SpecializeByConditional for DataDomain<T>

source§

fn intersect(self, other: &Self) -> Result<Self, Error>

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.
source§

fn add_signed_less_equal_bound(self, bound: &Bitvector) -> Result<Self, Error>

Return the restriction of self to values satisfying self <= bound with self and bound interpreted as signed integers. Returns an error if no value represented by self can satisfy the comparison.
source§

fn add_unsigned_less_equal_bound(self, bound: &Bitvector) -> Result<Self, Error>

Return the restriction of self to values satisfying self <= bound with self and bound interpreted as unsigned integers. Returns an error if no value represented by self can satisfy the comparison.
source§

fn add_signed_greater_equal_bound( self, bound: &Bitvector ) -> Result<Self, Error>

Return the restriction of self to values satisfying self >= bound with self and bound interpreted as signed integers. Returns an error if no value represented by self can satisfy the comparison.
source§

fn add_unsigned_greater_equal_bound( self, bound: &Bitvector ) -> Result<Self, Error>

Return the restriction of self to values satisfying self >= bound with self and bound interpreted as unsigned integers. Returns an error if no value represented by self can satisfy the comparison.
source§

fn add_not_equal_bound(self, bound: &Bitvector) -> Result<Self, Error>

Return the restriction of self to values satisfying self != bound Returns an error if self only represents one value for which self == bound holds.
source§

fn without_widening_hints(self) -> Self

Remove all widening hints from self. Necessary for cases where several sources have widening hints, but only one source should contribute widening hints to the result.
source§

impl<T: RegisterDomain> Sub for DataDomain<T>

§

type Output = DataDomain<T>

The resulting type after applying the - operator.
source§

fn sub(self, rhs: Self) -> Self

Performs the - operation. Read more
source§

impl<T: RegisterDomain + TryToBitvec> TryToBitvec for DataDomain<T>

source§

fn try_to_bitvec(&self) -> Result<Bitvector, Error>

If the domain represents a single, absolute value, return it.

source§

fn try_to_offset(&self) -> Result<i64, Error>

If self represents a single absolute value, try to convert it to a signed integer and return it. Else return an error. Note that the conversion loses information about the bytesize of the value.
source§

impl<T: RegisterDomain + TryToInterval> TryToInterval for DataDomain<T>

source§

fn try_to_interval(&self) -> Result<Interval, Error>

If the domain represents (or can be widened to) an interval of absolute values, return the interval.

source§

fn try_to_offset_interval(&self) -> Result<(i64, i64), Error>

If self represents an interval of absolute values (or can be widened to represent such an interval) then return it as an interval of signed integers of the form (start, end) if the interval is bounded. Else return an error. Note that the conversion loses information about the bytesize of the values contained in the interval.
source§

impl<T: Eq + RegisterDomain> Eq for DataDomain<T>

source§

impl<T: RegisterDomain> StructuralEq for DataDomain<T>

source§

impl<T: RegisterDomain> StructuralPartialEq for DataDomain<T>

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for DataDomain<T>
where T: RefUnwindSafe,

§

impl<T> Send for DataDomain<T>
where T: Send,

§

impl<T> Sync for DataDomain<T>
where T: Sync,

§

impl<T> Unpin for DataDomain<T>
where T: Unpin,

§

impl<T> UnwindSafe for DataDomain<T>

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
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
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> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
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.
source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,