Source code for angr.knowledge_plugins.key_definitions.environment

from typing import Dict, Tuple, Union, Set

import claripy

from .undefined import Undefined, UNDEFINED


[docs]class Environment: """ Represent the environment in which a program runs. It's a mapping of variable names, to `claripy.ast.Base` that should contain possible addresses, or <UNDEFINED>, at which their respective values are stored. **Note**: The <Environment> object does not store the values associated with variables themselves. """
[docs] def __init__(self, environment: Dict[Union[str, Undefined], Set[claripy.ast.Base]] = None): self._environment: Dict[Union[str, Undefined], Set[claripy.ast.Base]] = environment or {}
[docs] def get(self, names: Set[str]) -> Tuple[Set[claripy.ast.Base], bool]: """ :param names: Potential values for the name of the environment variable to get the pointers of. :return: The potential addresses of the values the environment variable can take; And a boolean value telling whether all the names were known of the internal representation (i.e. will be False if one of the queried variable was not found). """ has_unknown = not all(map(lambda name: name in self._environment.keys(), names)) def _get(name): if not isinstance(name, (str, Undefined)): raise TypeError("get(): Expected str, or Undefined, got %s" % type(name).__name__) return self._environment.get(name, {UNDEFINED}) pointers = set() for values in map(_get, names): pointers |= values return pointers, has_unknown
[docs] def set(self, name: Union[str, Undefined], pointers: Set[claripy.ast.Base]): """ :param name: Name of the environment variable to which we will associate the pointers. :param pointers: New addresses where the new values of the environment variable are located. """ if not isinstance(name, (str, Undefined)): raise TypeError("set(): Expected str, or Undefined, got %s" % type(name).__name__) self._environment[name] = pointers
def __str__(self): return "Environment: %s" % self._environment def __repr__(self): return "Environment: %s" % self._environment def __eq__(self, other: object) -> bool: assert isinstance(other, Environment), "Cannot compare Environment with %s" % type(other).__name__ return self._environment == other._environment
[docs] def merge(self, *others: "Environment") -> Tuple["Environment", bool]: new_env = self._environment for other in others: if not isinstance(other, Environment): raise TypeError("Cannot merge Environment with %s" % type(other).__name__) keys = set(new_env.keys()) keys |= other._environment.keys() def _dataset_from_key(key, environment1, environment2): v = environment1.get(key, None) w = environment2.get(key, None) # Because the key is coming from one of them, they cannot be both `None`. if v is None: return w if w is None: return v return v | w new_env = dict(map(lambda k: (k, _dataset_from_key(k, new_env, other._environment)), keys)) merge_occurred = new_env != self._environment return Environment(environment=new_env), merge_occurred