diff options
| -rw-r--r-- | miasm2/analysis/expression_range.py | 1 | ||||
| -rw-r--r-- | miasm2/analysis/modularintervals.py | 34 | ||||
| -rw-r--r-- | test/analysis/modularintervals.py | 7 | ||||
| -rw-r--r-- | test/analysis/range.py | 5 |
4 files changed, 44 insertions, 3 deletions
diff --git a/miasm2/analysis/expression_range.py b/miasm2/analysis/expression_range.py index ca63588c..a2c4a8df 100644 --- a/miasm2/analysis/expression_range.py +++ b/miasm2/analysis/expression_range.py @@ -7,6 +7,7 @@ _op_range_handler = { "&": lambda x, y: x & y, "|": lambda x, y: x | y, "^": lambda x, y: x ^ y, + "*": lambda x, y: x * y, ">>": lambda x, y: x >> y, "a>>": lambda x, y: x.arithmetic_shift_right(y), "<<": lambda x, y: x << y, diff --git a/miasm2/analysis/modularintervals.py b/miasm2/analysis/modularintervals.py index 0752f57b..650dbc21 100644 --- a/miasm2/analysis/modularintervals.py +++ b/miasm2/analysis/modularintervals.py @@ -22,8 +22,10 @@ class ModularIntervals(object): # Sanity check start, end = intervals.hull() - assert end <= self.mask - assert start >= 0 + if start is not None: + assert start >= 0 + if end is not None: + assert end <= self.mask # Helpers @@ -259,6 +261,21 @@ class ModularIntervals(object): _interval_xor = _range2interval(_range_xor) + def _range_mul(self, x_min, x_max, y_min, y_max): + """Interval bounds for x * y, with + - x, y of size self.size + - @x_min <= x <= @x_max + - @y_min <= y <= @y_max + - operations are considered unsigned + This is a naive version, going to TOP on overflow""" + max_bound = self.mask + if y_max * x_max > max_bound: + return interval([(0, max_bound)]) + else: + return interval([(x_min * y_min, x_max * y_max)]) + + _interval_mul = _range2interval(_range_mul) + def _range_mod_uniq(self, x_min, x_max, mod): """Interval bounds for x % @mod, with - x, @mod of size self.size @@ -388,11 +405,18 @@ class ModularIntervals(object): @_promote def __xor__(self, to_xor): """Bitwise XOR @to_xor to the current intervals - @to_or: ModularInstances or integer + @to_xor: ModularInstances or integer """ return self._interval_xor(to_xor) @_promote + def __mul__(self, to_mul): + """Multiply @to_mul to the current intervals + @to_mul: ModularInstances or integer + """ + return self._interval_mul(to_mul) + + @_promote def __rshift__(self, to_shift): """Logical shift right the current intervals of @to_shift @to_shift: ModularInstances or integer @@ -450,6 +474,10 @@ class ModularIntervals(object): def __iter__(self): return iter(self.intervals) + @property + def length(self): + return self.intervals.length + def __contains__(self, other): if isinstance(other, ModularIntervals): other = other.intervals diff --git a/test/analysis/modularintervals.py b/test/analysis/modularintervals.py index 36a29aa8..45aa82bd 100644 --- a/test/analysis/modularintervals.py +++ b/test/analysis/modularintervals.py @@ -89,6 +89,13 @@ def test(left, right): rez = (x ^ y) & mask assert rez in result + # Check MUL + result = left_i * right_i + for x in left_values: + for y in right_values: + rez = (x * y) & mask + assert rez in result + # Check >> result = left_i >> right_i for x in left_values: diff --git a/test/analysis/range.py b/test/analysis/range.py index 8b1224f9..0e38ec95 100644 --- a/test/analysis/range.py +++ b/test/analysis/range.py @@ -55,6 +55,11 @@ for expr in [ ExprInt(33, 8) % ExprInt(8, 8), a % a, a[:2].zeroExtend(8) + ExprInt(0xF, 8) % ExprCond(a[0:1], ExprInt(5, 8), ExprInt(18, 8)), + ExprInt(33, 8) * ExprInt(8, 8), + a * a, + a * ExprInt(0, 8), + ExprInt(4, 8) * a, + (a[:2].zeroExtend(8) + ExprInt(0xF, 8)) * ExprCond(a[0:1], ExprInt(5, 8), ExprInt(18, 8)), ExprOp("<<<", ExprInt(4, 8), ExprInt(1, 8)), ExprOp("<<<", ExprInt(4, 8), ExprInt(14, 8)), ExprOp("<<<", ExprInt(4, 8), a), |