1import claripy
2
3
4class SimConcretizationStrategy:
5    """
6    Concretization strategies control the resolution of symbolic memory indices
7    in SimuVEX. By subclassing this class and setting it as a concretization strategy
8    (on state.memory.read_strategies and state.memory.write_strategies), SimuVEX's
9    memory index concretization behavior can be modified.
10    """
11
12    def __init__(self, filter=None, exact=True): #pylint:disable=redefined-builtin
13        """
14        Initializes the base SimConcretizationStrategy.
15
16        :param filter: A function, taking arguments of (SimMemory, claripy.AST) that determins
17                       if this strategy can handle resolving the provided AST.
18        :param exact: A flag (default: True) that determines if the convenience resolution
19                      functions provided by this class use exact or approximate resolution.
20        """
21        self._exact = exact
22        self._filter = filter
23
24    def _min(self, memory, addr, **kwargs):
25        """
26        Gets the minimum solution of an address.
27        """
28        return memory.state.solver.min(addr, exact=kwargs.pop('exact', self._exact), **kwargs)
29
30    def _max(self, memory, addr, **kwargs):
31        """
32        Gets the maximum solution of an address.
33        """
34        return memory.state.solver.max(addr, exact=kwargs.pop('exact', self._exact), **kwargs)
35
36    def _any(self, memory, addr, **kwargs):
37        """
38        Gets any solution of an address.
39        """
40        return memory.state.solver.eval(addr, exact=kwargs.pop('exact', self._exact), **kwargs)
41
42    def _eval(self, memory, addr, n, **kwargs):
43        """
44        Gets n solutions for an address.
45        """
46        if isinstance(addr, claripy.vsa.StridedInterval):
47            return addr.eval(n)
48        return memory.state.solver.eval_upto(addr, n, exact=kwargs.pop('exact', self._exact), **kwargs)
49
50    def _range(self, memory, addr, **kwargs):
51        """
52        Gets the (min, max) range of solutions for an address.
53        """
54        return (self._min(memory, addr, **kwargs), self._max(memory, addr, **kwargs))
55
56    def concretize(self, memory, addr):
57        """
58        Concretizes the address into a list of values.
59        If this strategy cannot handle this address, returns None.
60        """
61        if self._filter is None or self._filter(memory, addr):
62            return self._concretize(memory, addr)
63
64    def _concretize(self, memory, addr):
65        """
66        Should be implemented by child classes to handle concretization.
67        """
68        raise NotImplementedError()
69
70    def copy(self):
71        """
72        Returns a copy of the strategy, if there is data that should be kept separate between
73        states. If not, returns self.
74        """
75        return self
76
77    def merge(self, others):
78        """
79        Merges this strategy with others (if there is data that should be kept separate between
80        states. If not, is a no-op.
81        """
82        pass
83
84from .any import SimConcretizationStrategyAny
85from .controlled_data import SimConcretizationStrategyControlledData
86from .eval import SimConcretizationStrategyEval
87from .max import SimConcretizationStrategyMax
88from .nonzero import SimConcretizationStrategyNonzero
89from .nonzero_range import SimConcretizationStrategyNonzeroRange
90from .norepeats import SimConcretizationStrategyNorepeats
91from .norepeats_range import SimConcretizationStrategyNorepeatsRange
92from .range import SimConcretizationStrategyRange
93from .single import SimConcretizationStrategySingle
94from .solutions import SimConcretizationStrategySolutions
95from .unlimited_range import SimConcretizationStrategyUnlimitedRange
96