Source code for angr.storage.memory_mixins.default_filler_mixin

import logging

from . import MemoryMixin
from ... import sim_options as options
from ...misc.ux import once
from ...errors import SimMemoryMissingError

l = logging.getLogger(__name__)


[docs]class DefaultFillerMixin(MemoryMixin): def _default_value( self, addr, size, name=None, inspect=True, events=True, key=None, fill_missing: bool = True, **kwargs ): if self.state.project and self.state.project.concrete_target: mem = self.state.project.concrete_target.read_memory(addr, size) endness = kwargs["endness"] bvv = self.state.solver.BVV(mem) return bvv if endness == "Iend_BE" else bvv.reversed if fill_missing is False: raise SimMemoryMissingError(addr, size) bits = size * self.state.arch.byte_width if type(addr) is int: if self.category == "mem" and options.ZERO_FILL_UNCONSTRAINED_MEMORY in self.state.options: return self.state.solver.BVV(0, bits) elif self.category == "reg" and options.ZERO_FILL_UNCONSTRAINED_REGISTERS in self.state.options: return self.state.solver.BVV(0, bits) if self.category == "reg" and type(addr) is int and addr == self.state.arch.ip_offset: # short-circuit this pathological case return self.state.solver.BVV(0, self.state.arch.bits) is_mem = ( self.category == "mem" and options.ZERO_FILL_UNCONSTRAINED_MEMORY not in self.state.options and options.SYMBOL_FILL_UNCONSTRAINED_MEMORY not in self.state.options ) is_reg = ( self.category == "reg" and options.ZERO_FILL_UNCONSTRAINED_REGISTERS not in self.state.options and options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS not in self.state.options ) if type(addr) is int and (is_mem or is_reg): if once("mem_fill_warning"): what = "memory" if is_mem else "register" l.warning( "The program is accessing %s with an unspecified value. This could indicate unwanted behavior.", what, ) l.warning( "angr will cope with this by generating an unconstrained symbolic variable and continuing. " "You can resolve this by:" ) l.warning("1) setting a value to the initial state") l.warning( "2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, " "to make unknown regions hold null" ) l.warning( "3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, " "to suppress these messages." ) if is_mem: refplace_int = self.state.solver.eval(self.state._ip) if self.state.project: refplace_str = self.state.project.loader.describe_addr(refplace_int) else: refplace_str = "unknown" l.warning( "Filling memory at %#x with %d unconstrained bytes referenced from %#x (%s)", addr, size, refplace_int, refplace_str, ) else: if addr == self.state.arch.ip_offset: refplace_int = 0 refplace_str = "symbolic" else: refplace_int = self.state.solver.eval(self.state._ip) if self.state.project: refplace_str = self.state.project.loader.describe_addr(refplace_int) else: refplace_str = "unknown" reg_str = self.state.arch.translate_register_name(addr, size=size) l.warning( "Filling register %s with %d unconstrained bytes referenced from %#x (%s)", reg_str, size, refplace_int, refplace_str, ) if name is None and not reg_str.isdigit(): name = "reg_" + reg_str if name is None: if type(addr) is int: name = f"{self.id}_{addr:x}" else: name = self.category r = self.state.solver.Unconstrained(name, bits, key=key, inspect=inspect, events=events) return r
[docs]class SpecialFillerMixin(MemoryMixin):
[docs] def __init__(self, special_memory_filler=None, **kwargs): super().__init__(**kwargs) self._special_memory_filler = special_memory_filler
def _default_value(self, addr, size, name=None, **kwargs): if ( options.SPECIAL_MEMORY_FILL in self.state.options and self.state._special_memory_filler is not None and type(addr) is int ): return self.state._special_memory_filler(name, size * self.state.arch.byte_width, self.state) return super()._default_value(addr, size, name=name, **kwargs)
[docs] def copy(self, memo): o = super().copy(memo) o._special_memory_filler = self._special_memory_filler return o
[docs]class ExplicitFillerMixin(MemoryMixin):
[docs] def __init__(self, uninitialized_read_handler=None, **kwargs): super().__init__(**kwargs) self._uninitialized_read_handler = uninitialized_read_handler
def _default_value(self, addr, size, inspect=True, events=True, **kwargs): if self._uninitialized_read_handler is not None: return self._uninitialized_read_handler(addr, size, inspect=inspect, events=events) else: return super()._default_value(addr, size, inspect=inspect, events=events, **kwargs)
[docs] def copy(self, memo): o = super().copy(memo) o._uninitialized_read_handler = self._uninitialized_read_handler return o