[docs]classEnvironment:""" 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. """__slots__=("_environment",)
[docs]defget(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=notall(map(lambdaname:nameinself._environment.keys(),names))def_get(name):ifnotisinstance(name,(str,Undefined)):raiseTypeError("get(): Expected str, or Undefined, got %s"%type(name).__name__)returnself._environment.get(name,{UNDEFINED})pointers=set()forvaluesinmap(_get,names):pointers|=valuesreturnpointers,has_unknown
[docs]defset(self,name: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. """ifnotisinstance(name,(str,Undefined)):raiseTypeError("set(): Expected str, or Undefined, got %s"%type(name).__name__)self._environment[name]=pointers
def__str__(self):return"Environment: %s"%self._environmentdef__repr__(self):return"Environment: %s"%self._environmentdef__eq__(self,other:object)->bool:assertisinstance(other,Environment),"Cannot compare Environment with %s"%type(other).__name__returnself._environment==other._environment
[docs]defmerge(self,*others:"Environment")->tuple["Environment",bool]:new_env=self._environmentforotherinothers:ifnotisinstance(other,Environment):raiseTypeError("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`.ifvisNone:returnwifwisNone:returnvreturnv|wnew_env=dict(map(lambdak:(k,_dataset_from_key(k,new_env,other._environment)),keys))merge_occurred=new_env!=self._environmentreturnEnvironment(environment=new_env),merge_occurred