about summary refs log tree commit diff stats
path: root/miasm2/expression
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/expression')
-rw-r--r--miasm2/expression/expression.py106
-rw-r--r--miasm2/expression/expression_helper.py74
-rw-r--r--miasm2/expression/modint.py51
-rw-r--r--miasm2/expression/simplifications.py4
-rw-r--r--miasm2/expression/simplifications_common.py18
5 files changed, 157 insertions, 96 deletions
diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py
index 925190ca..03febbfd 100644
--- a/miasm2/expression/expression.py
+++ b/miasm2/expression/expression.py
@@ -29,11 +29,19 @@
 #
 
 
+from builtins import zip
+from builtins import range
 import warnings
 import itertools
+from builtins import int as int_types
+from functools import cmp_to_key, total_ordering
+from future.utils import viewitems
+
+from miasm2.core.utils import force_bytes, cmp_elts
 from miasm2.expression.modint import mod_size2uint, is_modint, size2mask, \
     define_uint
 from miasm2.core.graph import DiGraph
+from functools import reduce
 
 # Define tokens
 TOK_INF = "<"
@@ -145,7 +153,7 @@ class DiGraphExpr(DiGraph):
         return ""
 
 
-
+@total_ordering
 class LocKey(object):
     def __init__(self, key):
         self._key = key
@@ -163,7 +171,11 @@ class LocKey(object):
         return self.key == other.key
 
     def __ne__(self, other):
-        return not self.__eq__(other)
+        # required Python 2.7.14
+        return not self == other
+
+    def __lt__(self, other):
+        return self.key < other.key
 
     def __repr__(self):
         return "<%s %d>" % (self.__class__.__name__, self._key)
@@ -202,11 +214,11 @@ class Expr(object):
     @staticmethod
     def get_object(expr_cls, args):
         if not expr_cls.use_singleton:
-            return object.__new__(expr_cls, args)
+            return object.__new__(expr_cls)
 
         expr = Expr.args2expr.get((expr_cls, args))
         if expr is None:
-            expr = object.__new__(expr_cls, args)
+            expr = object.__new__(expr_cls)
             Expr.args2expr[(expr_cls, args)] = expr
         return expr
 
@@ -276,6 +288,9 @@ class Expr(object):
     def __div__(self, other):
         return ExprOp('/', self, other)
 
+    def __floordiv__(self, other):
+        return self.__div__(other)
+
     def __mod__(self, other):
         return ExprOp('%', self, other)
 
@@ -524,7 +539,7 @@ class ExprInt(Expr):
         return int(self.arg)
 
     def __long__(self):
-        return long(self.arg)
+        return int(self.arg)
 
     def is_int(self, value=None):
         if value is not None and self._arg != value:
@@ -552,7 +567,7 @@ class ExprId(Expr):
         if size is None:
             warnings.warn('DEPRECATION WARNING: size is a mandatory argument: use ExprId(name, SIZE)')
             size = 32
-        assert isinstance(name, str)
+        assert isinstance(name, (str, bytes))
         super(ExprId, self).__init__(size)
         self._name = name
 
@@ -896,7 +911,7 @@ class ExprMem(Expr):
 
         # ptr must be Expr
         assert isinstance(ptr, Expr)
-        assert isinstance(size, (int, long))
+        assert isinstance(size, int_types)
 
         if not isinstance(ptr, Expr):
             raise ValueError(
@@ -1169,8 +1184,8 @@ class ExprSlice(Expr):
 
         # arg must be Expr
         assert isinstance(arg, Expr)
-        assert isinstance(start, (int, long))
-        assert isinstance(stop, (int, long))
+        assert isinstance(start, int_types)
+        assert isinstance(stop, int_types)
         assert start < stop
 
         self._arg, self._start, self._stop = arg, start, stop
@@ -1344,45 +1359,46 @@ class ExprCompose(Expr):
         return True
 
 # Expression order for comparison
-EXPR_ORDER_DICT = {ExprId: 1,
-                   ExprLoc: 2,
-                   ExprCond: 3,
-                   ExprMem: 4,
-                   ExprOp: 5,
-                   ExprSlice: 6,
-                   ExprCompose: 7,
-                   ExprInt: 8,
-                  }
+EXPR_ORDER_DICT = {
+    ExprId: 1,
+    ExprLoc: 2,
+    ExprCond: 3,
+    ExprMem: 4,
+    ExprOp: 5,
+    ExprSlice: 6,
+    ExprCompose: 7,
+    ExprInt: 8,
+}
 
 
 def compare_exprs_compose(expr1, expr2):
-    # Sort by start bit address, then expr, then stop but address
-    ret = cmp(expr1[1], expr2[1])
+    # Sort by start bit address, then expr, then stop bit address
+    ret = cmp_elts(expr1[1], expr2[1])
     if ret:
         return ret
     ret = compare_exprs(expr1[0], expr2[0])
     if ret:
         return ret
-    ret = cmp(expr1[2], expr2[2])
+    ret = cmp_elts(expr1[2], expr2[2])
     return ret
 
 
 def compare_expr_list_compose(l1_e, l2_e):
     # Sort by list elements in incremental order, then by list size
-    for i in xrange(min(len(l1_e), len(l2_e))):
+    for i in range(min(len(l1_e), len(l2_e))):
         ret = compare_exprs(l1_e[i], l2_e[i])
         if ret:
             return ret
-    return cmp(len(l1_e), len(l2_e))
+    return cmp_elts(len(l1_e), len(l2_e))
 
 
 def compare_expr_list(l1_e, l2_e):
     # Sort by list elements in incremental order, then by list size
-    for i in xrange(min(len(l1_e), len(l2_e))):
+    for i in range(min(len(l1_e), len(l2_e))):
         ret = compare_exprs(l1_e[i], l2_e[i])
         if ret:
             return ret
-    return cmp(len(l1_e), len(l2_e))
+    return cmp_elts(len(l1_e), len(l2_e))
 
 
 def compare_exprs(expr1, expr2):
@@ -1396,27 +1412,30 @@ def compare_exprs(expr1, expr2):
     cls1 = expr1.__class__
     cls2 = expr2.__class__
     if cls1 != cls2:
-        return cmp(EXPR_ORDER_DICT[cls1], EXPR_ORDER_DICT[cls2])
+        return cmp_elts(EXPR_ORDER_DICT[cls1], EXPR_ORDER_DICT[cls2])
     if expr1 == expr2:
         return 0
     if cls1 == ExprInt:
-        ret = cmp(expr1.size, expr2.size)
+        ret = cmp_elts(expr1.size, expr2.size)
         if ret != 0:
             return ret
-        return cmp(expr1.arg, expr2.arg)
+        return cmp_elts(expr1.arg, expr2.arg)
     elif cls1 == ExprId:
-        ret = cmp(expr1.name, expr2.name)
+        name1 = force_bytes(expr1.name)
+        name2 = force_bytes(expr2.name)
+        ret = cmp_elts(name1, name2)
         if ret:
             return ret
-        return cmp(expr1.size, expr2.size)
+        return cmp_elts(expr1.size, expr2.size)
     elif cls1 == ExprLoc:
-        ret = cmp(expr1.loc_key, expr2.loc_key)
+        ret = cmp_elts(expr1.loc_key, expr2.loc_key)
         if ret:
             return ret
-        return cmp(expr1.size, expr2.size)
+        return cmp_elts(expr1.size, expr2.size)
     elif cls1 == ExprAssign:
         raise NotImplementedError(
-            "Comparison from an ExprAssign not yet implemented")
+            "Comparison from an ExprAssign not yet implemented"
+        )
     elif cls2 == ExprCond:
         ret = compare_exprs(expr1.cond, expr2.cond)
         if ret:
@@ -1430,36 +1449,33 @@ def compare_exprs(expr1, expr2):
         ret = compare_exprs(expr1.ptr, expr2.ptr)
         if ret:
             return ret
-        return cmp(expr1.size, expr2.size)
+        return cmp_elts(expr1.size, expr2.size)
     elif cls1 == ExprOp:
         if expr1.op != expr2.op:
-            return cmp(expr1.op, expr2.op)
+            return cmp_elts(expr1.op, expr2.op)
         return compare_expr_list(expr1.args, expr2.args)
     elif cls1 == ExprSlice:
         ret = compare_exprs(expr1.arg, expr2.arg)
         if ret:
             return ret
-        ret = cmp(expr1.start, expr2.start)
+        ret = cmp_elts(expr1.start, expr2.start)
         if ret:
             return ret
-        ret = cmp(expr1.stop, expr2.stop)
+        ret = cmp_elts(expr1.stop, expr2.stop)
         return ret
     elif cls1 == ExprCompose:
         return compare_expr_list_compose(expr1.args, expr2.args)
     raise NotImplementedError(
-        "Comparison between %r %r not implemented" % (expr1, expr2))
+        "Comparison between %r %r not implemented" % (expr1, expr2)
+    )
 
 
 def canonize_expr_list(expr_list):
-    expr_list = list(expr_list)
-    expr_list.sort(cmp=compare_exprs)
-    return expr_list
+    return sorted(expr_list, key=cmp_to_key(compare_exprs))
 
 
 def canonize_expr_list_compose(expr_list):
-    expr_list = list(expr_list)
-    expr_list.sort(cmp=compare_exprs_compose)
-    return expr_list
+    return sorted(expr_list, key=cmp_to_key(compare_exprs_compose))
 
 # Generate ExprInt with common size
 
@@ -1604,7 +1620,7 @@ def match_expr(expr, pattern, tks, result=None):
                     break
             if good is True:
                 # We found a possibility
-                for joker, value in myresult.items():
+                for joker, value in viewitems(myresult):
                     # Updating result in place (to keep pointer in recursion)
                     result[joker] = value
                 return result
diff --git a/miasm2/expression/expression_helper.py b/miasm2/expression/expression_helper.py
index 8065df9b..a50e0d5b 100644
--- a/miasm2/expression/expression_helper.py
+++ b/miasm2/expression/expression_helper.py
@@ -17,17 +17,20 @@
 #
 
 # Expressions manipulation functions
+from builtins import range
 import itertools
 import collections
 import random
 import string
 import warnings
 
+from future.utils import viewitems, viewvalues
+
 import miasm2.expression.expression as m2_expr
 
 
 def parity(a):
-    tmp = (a) & 0xFFL
+    tmp = (a) & 0xFF
     cpt = 1
     while tmp != 0:
         cpt ^= tmp & 1
@@ -174,13 +177,15 @@ class Variables_Identifier(object):
         has_change = True
         while has_change:
             has_change = False
-            for var_id, var_value in self._vars.iteritems():
+            for var_id, var_value in list(viewitems(self._vars)):
                 cur = var_value
 
                 # Do not replace with itself
-                to_replace = {v_val:v_id
-                              for v_id, v_val in self._vars.iteritems()
-                              if v_id != var_id}
+                to_replace = {
+                    v_val:v_id
+                    for v_id, v_val in viewitems(self._vars)
+                    if v_id != var_id
+                }
                 var_value = var_value.replace_expr(to_replace)
 
                 if cur != var_value:
@@ -190,23 +195,29 @@ class Variables_Identifier(object):
                     break
 
         # Replace in the original equation
-        self._equation = expr.replace_expr({v_val: v_id for v_id, v_val
-                                            in self._vars.iteritems()})
+        self._equation = expr.replace_expr(
+            {
+                v_val: v_id for v_id, v_val
+                in viewitems(self._vars)
+            }
+        )
 
         # Compute variables dependencies
         self._vars_ordered = collections.OrderedDict()
-        todo = set(self._vars.iterkeys())
+        todo = set(self._vars)
         needs = {}
 
         ## Build initial needs
-        for var_id, var_expr in self._vars.iteritems():
+        for var_id, var_expr in viewitems(self._vars):
             ### Handle corner cases while using Variable Identifier on an
             ### already computed equation
-            needs[var_id] = [var_name
-                             for var_name in var_expr.get_r(mem_read=True)
-                             if self.is_var_identifier(var_name) and \
-                                 var_name in todo and \
-                                 var_name != var_id]
+            needs[var_id] = [
+                var_name
+                for var_name in var_expr.get_r(mem_read=True)
+                if self.is_var_identifier(var_name) and \
+                var_name in todo and \
+                var_name != var_id
+            ]
 
         ## Build order list
         while todo:
@@ -244,12 +255,15 @@ class Variables_Identifier(object):
 
         if (expr in self.var_asked):
             # Expr has already been asked
-
-            if (expr not in self._vars.values()):
+            if expr not in viewvalues(self._vars):
                 # Create var
-                identifier = m2_expr.ExprId("%s%s" % (self.var_prefix,
-                                                      self.var_indice.next()),
-                                            size = expr.size)
+                identifier = m2_expr.ExprId(
+                    "%s%s" % (
+                        self.var_prefix,
+                        next(self.var_indice)
+                    ),
+                    size = expr.size
+                )
                 self._vars[identifier] = expr
 
             # Recursion stop case
@@ -300,7 +314,7 @@ class Variables_Identifier(object):
     def __str__(self):
         "Display variables and final equation"
         out = ""
-        for var_id, var_expr in self.vars.iteritems():
+        for var_id, var_expr in viewitems(self.vars):
             out += "%s = %s\n" % (var_id, var_expr)
         out += "Final: %s" % self.equation
         return out
@@ -312,7 +326,7 @@ class ExprRandom(object):
     # Identifiers length
     identifier_len = 5
     # Identifiers' name charset
-    identifier_charset = string.letters
+    identifier_charset = string.ascii_letters
     # Number max value
     number_max = 0xFFFFFFFF
     # Available operations
@@ -340,7 +354,7 @@ class ExprRandom(object):
         @size: (optional) identifier size
         """
         return m2_expr.ExprId("".join([random.choice(cls.identifier_charset)
-                                       for _ in xrange(cls.identifier_len)]),
+                                       for _ in range(cls.identifier_len)]),
                               size=size)
 
     @classmethod
@@ -365,15 +379,17 @@ class ExprRandom(object):
         @size: (optional) Operation size
         @depth: (optional) Expression depth
         """
-        operand_type = random.choice(cls.operations_by_args_number.keys())
+        operand_type = random.choice(list(cls.operations_by_args_number))
         if isinstance(operand_type, str) and "+" in operand_type:
-            number_args = random.randint(int(operand_type[:-1]),
-                                         cls.operations_max_args_number)
+            number_args = random.randint(
+                int(operand_type[:-1]),
+                cls.operations_max_args_number
+            )
         else:
             number_args = operand_type
 
         args = [cls._gen(size=size, depth=depth - 1)
-                for _ in xrange(number_args)]
+                for _ in range(number_args)]
         operand = random.choice(cls.operations_by_args_number[operand_type])
         return m2_expr.ExprOp(operand,
                               *args)
@@ -593,8 +609,10 @@ def possible_values(expr):
     elif isinstance(expr, m2_expr.ExprCompose):
         # Generate each possibility for sub-argument, associated with the start
         # and stop bit
-        consvals_args = [map(lambda x: x, possible_values(arg))
-                         for arg in expr.args]
+        consvals_args = [
+            list(possible_values(arg))
+            for arg in expr.args
+        ]
         for consvals_possibility in itertools.product(*consvals_args):
             # Merge constraint of each sub-element
             args_constraint = itertools.chain(*[consval.constraints
diff --git a/miasm2/expression/modint.py b/miasm2/expression/modint.py
index 51a2620e..22d17b9b 100644
--- a/miasm2/expression/modint.py
+++ b/miasm2/expression/modint.py
@@ -1,9 +1,13 @@
 #-*- coding:utf-8 -*-
 
+from builtins import range
+from functools import total_ordering
+
+@total_ordering
 class moduint(object):
 
     def __init__(self, arg):
-        self.arg = long(arg) % self.__class__.limit
+        self.arg = int(arg) % self.__class__.limit
         assert(self.arg >= 0 and self.arg < self.__class__.limit)
 
     def __repr__(self):
@@ -20,11 +24,19 @@ class moduint(object):
         else:
             return c2
 
-    def __cmp__(self, y):
+    def __eq__(self, y):
         if isinstance(y, moduint):
-            return cmp(self.arg, y.arg)
-        else:
-            return cmp(self.arg, y)
+            return self.arg == y.arg
+        return self.arg == y
+
+    def __ne__(self, y):
+        # required Python 2.7.14
+        return not self == y
+
+    def __lt__(self, y):
+        if isinstance(y, moduint):
+            return self.arg < y.arg
+        return self.arg < y
 
     def __add__(self, y):
         if isinstance(y, moduint):
@@ -49,13 +61,19 @@ class moduint(object):
         cls = self.__class__
         if isinstance(y, moduint):
             cls = self.maxcast(y)
-        return ((abs(num) / abs(den)) * result_sign)
+        return (abs(num) // abs(den)) * result_sign
+
+    def __floordiv__(self, y):
+        return self.__div__(y)
 
     def __int__(self):
         return int(self.arg)
 
     def __long__(self):
-        return long(self.arg)
+        return int(self.arg)
+
+    def __index__(self):
+        return int(self.arg)
 
     def __invert__(self):
         return self.__class__(~self.arg)
@@ -72,7 +90,7 @@ class moduint(object):
         cls = self.__class__
         if isinstance(y, moduint):
             cls = self.maxcast(y)
-        return cls(self.arg - (y * (self / y)))
+        return cls(self.arg - y * (self // y))
 
     def __mul__(self, y):
         if isinstance(y, moduint):
@@ -100,9 +118,12 @@ class moduint(object):
     def __rdiv__(self, y):
         if isinstance(y, moduint):
             cls = self.maxcast(y)
-            return cls(y.arg / self.arg)
+            return cls(y.arg // self.arg)
         else:
-            return self.__class__(y / self.arg)
+            return self.__class__(y // self.arg)
+
+    def __rfloordiv__(self, y):
+        return self.__rdiv__(y)
 
     def __rlshift__(self, y):
         if isinstance(y, moduint):
@@ -181,11 +202,13 @@ class modint(moduint):
         if isinstance(arg, moduint):
             arg = arg.arg
         a = arg % self.__class__.limit
-        if a >= self.__class__.limit / 2:
+        if a >= self.__class__.limit // 2:
             a -= self.__class__.limit
         self.arg = a
-        assert(self.arg >= -self.__class__.limit /
-               2 and self.arg < self.__class__.limit)
+        assert(
+            self.arg >= -self.__class__.limit // 2 and
+            self.arg < self.__class__.limit
+        )
 
 
 def is_modint(a):
@@ -225,7 +248,7 @@ def define_uint(size):
 
 def define_common_int():
     "Define common int"
-    common_int = xrange(1, 257)
+    common_int = range(1, 257)
 
     for i in common_int:
         define_int(i)
diff --git a/miasm2/expression/simplifications.py b/miasm2/expression/simplifications.py
index 483331a6..331018ae 100644
--- a/miasm2/expression/simplifications.py
+++ b/miasm2/expression/simplifications.py
@@ -4,6 +4,8 @@
 
 import logging
 
+from future.utils import viewitems
+
 from miasm2.expression import simplifications_common
 from miasm2.expression import simplifications_cond
 from miasm2.expression import simplifications_explicit
@@ -126,7 +128,7 @@ class ExpressionSimplifier(object):
         # Clear cache of simplifiied expressions when adding a new pass
         self.simplified_exprs.clear()
 
-        for k, v in passes.items():
+        for k, v in viewitems(passes):
             self.expr_simp_cb[k] = fast_unify(self.expr_simp_cb.get(k, []) + v)
 
     def apply_simp(self, expression):
diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py
index a4b7c61e..ddcfc668 100644
--- a/miasm2/expression/simplifications_common.py
+++ b/miasm2/expression/simplifications_common.py
@@ -2,6 +2,7 @@
 # Common simplifications passes #
 # ----------------------------- #
 
+from future.utils import viewitems
 
 from miasm2.expression.modint import mod_size2int, mod_size2uint
 from miasm2.expression.expression import ExprInt, ExprSlice, ExprMem, \
@@ -70,14 +71,14 @@ def simp_cst_propagation(e_s, expr):
                 shifter = int2.arg % int2.size
                 out = (int1.arg << shifter) | (int1.arg >> (int2.size - shifter))
             elif op_name == '/':
-                out = int1.arg / int2.arg
+                out = int1.arg // int2.arg
             elif op_name == '%':
                 out = int1.arg % int2.arg
             elif op_name == 'sdiv':
                 assert int2.arg.arg
                 tmp1 = mod_size2int[int1.arg.size](int1.arg)
                 tmp2 = mod_size2int[int2.arg.size](int2.arg)
-                out = mod_size2uint[int1.arg.size](tmp1 / tmp2)
+                out = mod_size2uint[int1.arg.size](tmp1 // tmp2)
             elif op_name == 'smod':
                 assert int2.arg.arg
                 tmp1 = mod_size2int[int1.arg.size](int1.arg)
@@ -92,7 +93,7 @@ def simp_cst_propagation(e_s, expr):
                 assert int2.arg.arg
                 tmp1 = mod_size2uint[int1.arg.size](int1.arg)
                 tmp2 = mod_size2uint[int2.arg.size](int2.arg)
-                out = mod_size2uint[int1.arg.size](tmp1 / tmp2)
+                out = mod_size2uint[int1.arg.size](tmp1 // tmp2)
 
 
 
@@ -151,7 +152,8 @@ def simp_cst_propagation(e_s, expr):
         if len(args) > 2:
             raise ValueError(
                 'sanity check fail on expr -: should have one or 2 args ' +
-                '%r %s' % (expr, expr))
+                '%r %s' % (expr, expr)
+            )
         return ExprOp('+', args[0], -args[1])
 
     # A op 0 => 0
@@ -445,7 +447,7 @@ def simp_cond_factor(e_s, expr):
 
     # Rebuild the new expression
     c_out = not_conds
-    for cond, vals in conds.items():
+    for cond, vals in viewitems(conds):
         new_src1 = [x.src1 for x in vals]
         new_src2 = [x.src2 for x in vals]
         src1 = e_s.expr_simp_wrapper(ExprOp(expr.op, *new_src1))
@@ -583,7 +585,7 @@ def simp_compose(e_s, expr):
         nxt = args[i + 1]
         if arg.is_mem() and nxt.is_mem():
             gap = e_s(nxt.ptr - arg.ptr)
-            if gap.is_int() and arg.size % 8 == 0 and int(gap) == arg.size / 8:
+            if gap.is_int() and arg.size % 8 == 0 and int(gap) == arg.size // 8:
                 args = args[:i] + [ExprMem(arg.ptr,
                                           arg.size + nxt.size)] + args[i + 2:]
                 return ExprCompose(*args)
@@ -1520,7 +1522,7 @@ def simp_add_multiple(_, expr):
     modified = True
     while modified:
         modified = False
-        for arg, count in operands.iteritems():
+        for arg, count in list(viewitems(operands)):
             if not arg.is_op('+'):
                 continue
             components = arg.args
@@ -1536,7 +1538,7 @@ def simp_add_multiple(_, expr):
             modified = True
             break
 
-    for arg, count in operands.iteritems():
+    for arg, count in viewitems(operands):
         if count == 0:
             continue
         if count == 1: