about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorserpilliere <serpilliere@users.noreply.github.com>2017-03-30 16:50:42 +0200
committerGitHub <noreply@github.com>2017-03-30 16:50:42 +0200
commit0457001e8ffad3896997e3dc237ff3a557beb784 (patch)
tree3fca770e9ba8bd395a4f675dabd785d0ee0c3543
parent7947f33a61118c35a6b24aaac29337e2739216b4 (diff)
parent8c211caed99021a3654c14db4cdc5c6ff0b612ee (diff)
downloadmiasm-0457001e8ffad3896997e3dc237ff3a557beb784.tar.gz
miasm-0457001e8ffad3896997e3dc237ff3a557beb784.zip
Merge pull request #510 from commial/feature/modinterval-mul
Feature/modinterval mul
-rw-r--r--miasm2/analysis/expression_range.py1
-rw-r--r--miasm2/analysis/modularintervals.py34
-rw-r--r--test/analysis/modularintervals.py7
-rw-r--r--test/analysis/range.py5
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),