about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/expression/expression.py92
-rw-r--r--miasm2/expression/expression_helper.py166
-rw-r--r--miasm2/expression/simplifications.py1
-rw-r--r--miasm2/expression/simplifications_common.py149
-rw-r--r--miasm2/ir/ir.py15
-rw-r--r--miasm2/ir/symbexec.py6
-rw-r--r--miasm2/ir/translators/C.py8
-rw-r--r--miasm2/ir/translators/miasm.py3
-rw-r--r--miasm2/ir/translators/python.py8
-rw-r--r--miasm2/ir/translators/smt2.py6
-rw-r--r--miasm2/ir/translators/z3_ir.py6
11 files changed, 174 insertions, 286 deletions
diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py
index cb9f6114..324d5fea 100644
--- a/miasm2/expression/expression.py
+++ b/miasm2/expression/expression.py
@@ -288,11 +288,6 @@ class Expr(object):
                     new_e = ExprOp(e.op, *args)
                 else:
                     new_e = e
-            elif isinstance(e, ExprCompose):
-                starts = [start for (_, start, _) in e.args]
-                assert sorted(starts) == starts
-                assert len(set(starts)) == len(starts)
-                new_e = e
             else:
                 new_e = e
             new_e.is_canon = True
@@ -591,24 +586,6 @@ class ExprAff(Expr):
                 self.__src.__contains__(expr) or
                 self.__dst.__contains__(expr))
 
-    # XXX /!\ for hackish expraff to slice
-    def get_modified_slice(self):
-        """Return an Expr list of extra expressions needed during the
-        object instanciation"""
-
-        dst = self.__dst
-        if not isinstance(self.__src, ExprCompose):
-            raise ValueError("Get mod slice not on expraff slice", str(self))
-        modified_s = []
-        for arg in self.__src.args:
-            if (not isinstance(arg[0], ExprSlice) or
-                    arg[0].arg != dst or
-                    arg[1] != arg[0].start or
-                    arg[2] != arg[0].stop):
-                # If x is not the initial expression
-                modified_s.append(arg)
-        return modified_s
-
     @visit_chk
     def visit(self, cb, tv=None):
         dst, src = self.__dst.visit(cb, tv), self.__src.visit(cb, tv)
@@ -1073,40 +1050,12 @@ class ExprCompose(Expr):
         super(ExprCompose, self).__init__()
 
         is_new_style = args and isinstance(args[0], Expr)
-        if is_new_style:
-            new_args = []
-            index = 0
-            for arg in args:
-                new_args.append((arg, index, index + arg.size))
-                index += arg.size
-            args = new_args
-        else:
+        if not is_new_style:
             warnings.warn('DEPRECATION WARNING: use "ExprCompose(a, b) instead of'+
                           'ExprCemul_ir_block(self, addr, step=False)" instead of emul_ir_bloc')
-            assert len(args) == 1
-            args = args[0]
 
-        last_stop = 0
-        args = sorted(args, key=itemgetter(1))
-        for e, start, stop in args:
-            if e.size != stop - start:
-                raise ValueError(
-                    "sanitycheck: ExprCompose args must have correct size!" +
-                    " %r %r %r" % (e, e.size, stop - start))
-            if last_stop != start:
-                raise ValueError(
-                    "sanitycheck: ExprCompose args must be contiguous!" +
-                    " %r" % (args))
-            last_stop = stop
-
-        # Transform args to lists
-        o = []
-        for e, a, b in args:
-            assert(a >= 0 and b >= 0)
-            o.append(tuple([e, a, b]))
-        self.__args = tuple(o)
-
-        self.__size = self.__args[-1][2]
+        self.__args = tuple(args)
+        self.__size = sum([arg.size for arg in args])
 
     size = property(lambda self: self.__size)
     args = property(lambda self: self.__args)
@@ -1125,19 +1074,18 @@ class ExprCompose(Expr):
         return Expr.get_object(cls, tuple(args))
 
     def __str__(self):
-        return '{' + ', '.join([str(arg[0]) for arg in self.__args]) + '}'
+        return '{' + ', '.join([str(arg) for arg in self.__args]) + '}'
 
     def get_r(self, mem_read=False, cst_read=False):
         return reduce(lambda elements, arg:
-                      elements.union(arg[0].get_r(mem_read, cst_read)), self.__args, set())
+                      elements.union(arg.get_r(mem_read, cst_read)), self.__args, set())
 
     def get_w(self):
         return reduce(lambda elements, arg:
-                      elements.union(arg[0].get_w()), self.__args, set())
+                      elements.union(arg.get_w()), self.__args, set())
 
     def _exprhash(self):
-        h_args = [EXPRCOMPOSE] + [(hash(arg[0]), arg[1], arg[2])
-                                  for arg in self.__args]
+        h_args = [EXPRCOMPOSE] + [hash(arg) for arg in self.__args]
         return hash(tuple(h_args))
 
     def _exprrepr(self):
@@ -1149,33 +1097,37 @@ class ExprCompose(Expr):
         for arg in self.__args:
             if arg == e:
                 return True
-            if arg[0].__contains__(e):
+            if arg.__contains__(e):
                 return True
         return False
 
     @visit_chk
     def visit(self, cb, tv=None):
-        args = [(arg[0].visit(cb, tv), arg[1], arg[2]) for arg in self.__args]
-        modified = any([arg[0] != arg[1] for arg in zip(self.__args, args)])
+        args = [arg.visit(cb, tv) for arg in self.__args]
+        modified = any([arg != arg_new for arg, arg_new in zip(self.__args, args)])
         if modified:
-            args = [expr for (expr, _, _) in args]
             return ExprCompose(*args)
         return self
 
     def copy(self):
-        args = [arg[0].copy() for arg in self.__args]
+        args = [arg.copy() for arg in self.__args]
         return ExprCompose(*args)
 
     def depth(self):
-        depth = [arg[0].depth() for arg in self.__args]
+        depth = [arg.depth() for arg in self.__args]
         return max(depth) + 1
 
     def graph_recursive(self, graph):
         graph.add_node(self)
         for arg in self.args:
-            arg[0].graph_recursive(graph)
-            graph.add_uniq_edge(self, arg[0])
+            arg.graph_recursive(graph)
+            graph.add_uniq_edge(self, arg)
 
+    def iter_args(self):
+        index = 0
+        for arg in self.__args:
+            yield index, arg
+            index += arg.size
 
 # Expression order for comparaison
 expr_order_dict = {ExprId: 1,
@@ -1203,7 +1155,7 @@ def compare_exprs_compose(e1, e2):
 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))):
-        x = compare_exprs_compose(l1_e[i], l2_e[i])
+        x = compare_exprs(l1_e[i], l2_e[i])
         if x:
             return x
     return cmp(len(l1_e), len(l2_e))
@@ -1434,9 +1386,7 @@ def MatchExpr(e, m, tks, result=None):
         if not isinstance(m, ExprCompose):
             return False
         for a1, a2 in zip(e.args, m.args):
-            if a1[1] != a2[1] or a1[2] != a2[2]:
-                return False
-            r = MatchExpr(a1[0], a2[0], tks, result)
+            r = MatchExpr(a1, a2, tks, result)
             if r is False:
                 return False
         return result
diff --git a/miasm2/expression/expression_helper.py b/miasm2/expression/expression_helper.py
index e9176658..8babba70 100644
--- a/miasm2/expression/expression_helper.py
+++ b/miasm2/expression/expression_helper.py
@@ -34,103 +34,76 @@ def parity(a):
     return cpt
 
 
-def merge_sliceto_slice(args):
-    sources = {}
-    non_slice = {}
-    sources_int = {}
-    for a in args:
-        if isinstance(a[0], m2_expr.ExprInt):
-            # sources_int[a.start] = a
-            # copy ExprInt because we will inplace modify arg just below
-            # /!\ TODO XXX never ever modify inplace args...
-            sources_int[a[1]] = (m2_expr.ExprInt(int(a[0]),
-                                                 a[2] - a[1]),
-                                 a[1],
-                                 a[2])
-        elif isinstance(a[0], m2_expr.ExprSlice):
-            if not a[0].arg in sources:
-                sources[a[0].arg] = []
-            sources[a[0].arg].append(a)
+def merge_sliceto_slice(expr):
+    """
+    Apply basic factorisation on ExprCompose sub compoenents
+    @expr: ExprCompose
+    """
+
+    slices_raw = []
+    other_raw = []
+    integers_raw = []
+    for index, arg in expr.iter_args():
+        if isinstance(arg, m2_expr.ExprInt):
+            integers_raw.append((index, arg))
+        elif isinstance(arg, m2_expr.ExprSlice):
+            slices_raw.append((index, arg))
         else:
-            non_slice[a[1]] = a
-    # find max stop to determine size
-    max_size = None
-    for a in args:
-        if max_size is None or max_size < a[2]:
-            max_size = a[2]
-
-    # first simplify all num slices
-    final_sources = []
-    sorted_s = []
-    for x in sources_int.values():
-        x = list(x)
-        # mask int
-        v = x[0].arg & ((1 << (x[2] - x[1])) - 1)
-        x[0] = m2_expr.ExprInt_from(x[0], v)
-        x = tuple(x)
-        sorted_s.append((x[1], x))
-    sorted_s.sort()
-    while sorted_s:
-        start, v = sorted_s.pop()
-        out = [m2_expr.ExprInt(v[0].arg), v[1], v[2]]
-        size = v[2] - v[1]
-        while sorted_s:
-            if sorted_s[-1][1][2] != start:
+            other_raw.append((index, arg))
+
+    # Find max stop to determine size
+    max_size = sum([arg.size for arg in expr.args])
+
+    integers_merged = []
+    # Merge consecutive integers
+    while integers_raw:
+        index, arg = integers_raw.pop()
+        new_size = arg.size
+        value = int(arg)
+        while integers_raw:
+            prev_index, prev_value = integers_raw[-1]
+            # Check if intergers are consecutive
+            if prev_index + prev_value.size != index:
                 break
-            s_start, s_stop = sorted_s[-1][1][1], sorted_s[-1][1][2]
-            size += s_stop - s_start
-            a = m2_expr.mod_size2uint[size](
-                (int(out[0]) << (out[1] - s_start)) +
-                 int(sorted_s[-1][1][0]))
-            out[0] = m2_expr.ExprInt(a)
-            sorted_s.pop()
-            out[1] = s_start
-        out[0] = m2_expr.ExprInt(int(out[0]), size)
-        final_sources.append((start, tuple(out)))
-
-    final_sources_int = final_sources
-    # check if same sources have corresponding start/stop
-    # is slice AND is sliceto
-    simp_sources = []
-    for args in sources.values():
-        final_sources = []
-        sorted_s = []
-        for x in args:
-            sorted_s.append((x[1], x))
-        sorted_s.sort()
-        while sorted_s:
-            start, v = sorted_s.pop()
-            ee = v[0].arg[v[0].start:v[0].stop]
-            out = ee, v[1], v[2]
-            while sorted_s:
-                if sorted_s[-1][1][2] != start:
-                    break
-                if sorted_s[-1][1][0].stop != out[0].start:
-                    break
-
-                start = sorted_s[-1][1][1]
-                # out[0].start = sorted_s[-1][1][0].start
-                o_e, _, o_stop = out
-                o1, o2 = sorted_s[-1][1][0].start, o_e.stop
-                o_e = o_e.arg[o1:o2]
-                out = o_e, start, o_stop
-                # update _size
-                # out[0]._size = out[0].stop-out[0].start
-                sorted_s.pop()
-            out = out[0], start, out[2]
-
-            final_sources.append((start, out))
+            # Merge integers
+            index = prev_index
+            new_size += prev_value.size
+            value = value << prev_value.size
+            value |= int(prev_value)
+            integers_raw.pop()
+        integers_merged.append((index, m2_expr.ExprInt(value, new_size)))
+
+
+    slices_merged = []
+    # Merge consecutive slices
+    while slices_raw:
+        index, arg = slices_raw.pop()
+        value, slice_start, slice_stop = arg.arg, arg.start, arg.stop
+        while slices_raw:
+            prev_index, prev_value = slices_raw[-1]
+            # Check if slices are consecutive
+            if prev_index + prev_value.size != index:
+                break
+            # Check if slices can ben merged
+            if prev_value.arg != value:
+                break
+            if prev_value.stop != slice_start:
+                break
+            # Merge slices
+            index = prev_index
+            slice_start = prev_value.start
+            slices_raw.pop()
+        slices_merged.append((index, value[slice_start:slice_stop]))
 
-        simp_sources += final_sources
 
-    simp_sources += final_sources_int
+    new_args = slices_merged + integers_merged + other_raw
+    new_args.sort()
+    for i, (index, arg) in enumerate(new_args[:-1]):
+        assert index + arg.size == new_args[i+1][0]
+    ret = [arg[1] for arg in new_args]
 
-    for i, v in non_slice.items():
-        simp_sources.append((i, v))
+    return ret
 
-    simp_sources.sort()
-    simp_sources = [x[1] for x in simp_sources]
-    return simp_sources
 
 
 op_propag_cst = ['+', '*', '^', '&', '|', '>>',
@@ -327,8 +300,8 @@ class Variables_Identifier(object):
             self.find_variables_rec(expr.arg)
 
         elif isinstance(expr, m2_expr.ExprCompose):
-            for a in expr.args:
-                self.find_variables_rec(list(a)[0])
+            for arg in expr.args:
+                self.find_variables_rec(arg)
 
         elif isinstance(expr, m2_expr.ExprSlice):
             self.find_variables_rec(expr.arg)
@@ -646,15 +619,14 @@ 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, arg[1], arg[2]),
-                             possible_values(arg[0]))
+        consvals_args = [map(lambda x: x, 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[0].constraints
+            args_constraint = itertools.chain(*[consval.constraints
                                                 for consval in consvals_possibility])
             # Gen the corresponding constraints / ExprCompose
-            args = [consval[0].value for consval in consvals_possibility]
+            args = [consval.value for consval in consvals_possibility]
             consvals.add(
                 ConstrainedValue(frozenset(args_constraint),
                                  m2_expr.ExprCompose(*args)))
diff --git a/miasm2/expression/simplifications.py b/miasm2/expression/simplifications.py
index 069be197..dd4f5c04 100644
--- a/miasm2/expression/simplifications.py
+++ b/miasm2/expression/simplifications.py
@@ -96,6 +96,7 @@ class ExpressionSimplifier(object):
             self.simplified_exprs.add(expression)
         # Mark expression as simplified
         self.simplified_exprs.add(e_new)
+
         return e_new
 
     def expr_simp_wrapper(self, expression, callback=None):
diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py
index 4b88f8c2..a070fb81 100644
--- a/miasm2/expression/simplifications_common.py
+++ b/miasm2/expression/simplifications_common.py
@@ -265,13 +265,14 @@ def simp_cst_propagation(e_s, e):
         args = new_args
 
     # A << int with A ExprCompose => move index
-    if op == "<<" and isinstance(args[0], ExprCompose) and isinstance(args[1], ExprInt):
+    if (op == "<<" and isinstance(args[0], ExprCompose) and
+        isinstance(args[1], ExprInt) and int(args[1]) != 0):
         final_size = args[0].size
         shift = int(args[1])
         new_args = []
         # shift indexes
-        for expr, start, stop in args[0].args:
-            new_args.append((expr, start+shift, stop+shift))
+        for index, arg in args[0].iter_args():
+            new_args.append((arg, index+shift, index+shift+arg.size))
         # filter out expression
         filter_args = []
         min_index = final_size
@@ -281,15 +282,12 @@ def simp_cst_propagation(e_s, e):
             if stop > final_size:
                 expr = expr[:expr.size  - (stop - final_size)]
                 stop = final_size
-            filter_args.append((expr, start, stop))
+            filter_args.append(expr)
             min_index = min(start, min_index)
         # create entry 0
+        assert min_index != 0
         expr = ExprInt(0, min_index)
-        filter_args = [(expr, 0, min_index)] + filter_args
-        filter_args.sort(key=lambda x:x[1])
-        starts = [start for (_, start, _) in filter_args]
-        assert len(set(starts)) == len(starts)
-        args = [expr for (expr, _, _) in filter_args]
+        args = [expr] + filter_args
         return ExprCompose(*args)
 
     # A >> int with A ExprCompose => move index
@@ -298,8 +296,8 @@ def simp_cst_propagation(e_s, e):
         shift = int(args[1])
         new_args = []
         # shift indexes
-        for expr, start, stop in args[0].args:
-            new_args.append((expr, start-shift, stop-shift))
+        for index, arg in args[0].iter_args():
+            new_args.append((arg, index-shift, index+arg.size-shift))
         # filter out expression
         filter_args = []
         max_index = 0
@@ -309,15 +307,11 @@ def simp_cst_propagation(e_s, e):
             if start < 0:
                 expr = expr[-start:]
                 start = 0
-            filter_args.append((expr, start, stop))
+            filter_args.append(expr)
             max_index = max(stop, max_index)
         # create entry 0
         expr = ExprInt(0, final_size - max_index)
-        filter_args += [(expr, max_index, final_size)]
-        filter_args.sort(key=lambda x:x[1])
-        starts = [start for (_, start, _) in filter_args]
-        assert len(set(starts)) == len(starts)
-        args = [expr for (expr, _, _) in filter_args]
+        args = filter_args + [expr]
         return ExprCompose(*args)
 
 
@@ -325,22 +319,17 @@ def simp_cst_propagation(e_s, e):
     if op in ['|', '&', '^'] and all([isinstance(arg, ExprCompose) for arg in args]):
         bounds = set()
         for arg in args:
-            bound = tuple([(start, stop) for (expr, start, stop) in arg.args])
+            bound = tuple([expr.size for expr in arg.args])
             bounds.add(bound)
         if len(bounds) == 1:
             bound = list(bounds)[0]
-            new_args = [[expr] for (expr, start, stop) in args[0].args]
+            new_args = [[expr] for expr in args[0].args]
             for sub_arg in args[1:]:
-                for i, (expr, start, stop) in enumerate(sub_arg.args):
+                for i, expr in enumerate(sub_arg.args):
                     new_args[i].append(expr)
+            args = []
             for i, arg in enumerate(new_args):
-                new_args[i] = ExprOp(op, *arg), bound[i][0], bound[i][1]
-
-            new_args.sort(key=lambda x:x[1])
-            starts = [start for (_, start, _) in new_args]
-            assert len(set(starts)) == len(starts)
-            args = [expr for (expr, _, _) in new_args]
-
+                args.append(ExprOp(op, *arg))
             return ExprCompose(*args)
 
     # <<<c_rez, >>>c_rez
@@ -462,46 +451,41 @@ def simp_slice(e_s, e):
         return new_e
     elif isinstance(e.arg, ExprCompose):
         # Slice(Compose(A), x) => Slice(A, y)
-        for a in e.arg.args:
-            if a[1] <= e.start and a[2] >= e.stop:
-                new_e = a[0][e.start - a[1]:e.stop - a[1]]
+        for index, arg in e.arg.iter_args():
+            if index <= e.start and index+arg.size >= e.stop:
+                new_e = arg[e.start - index:e.stop - index]
                 return new_e
         # Slice(Compose(A, B, C), x) => Compose(A, B, C) with truncated A/B/C
         out = []
-        for arg, s_start, s_stop in e.arg.args:
+        for index, arg in e.arg.iter_args():
             # arg is before slice start
-            if e.start >= s_stop:
+            if e.start >= index + arg.size:
                 continue
             # arg is after slice stop
-            elif e.stop <= s_start:
+            elif e.stop <= index:
                 continue
             # arg is fully included in slice
-            elif e.start <= s_start and s_stop <= e.stop:
-                out.append((arg, s_start - e.start, s_stop - e.start))
+            elif e.start <= index and index + arg.size <= e.stop:
+                out.append(arg)
                 continue
             # arg is truncated at start
-            if e.start > s_start:
-                slice_start = e.start - s_start
+            if e.start > index:
+                slice_start = e.start - index
                 a_start = 0
             else:
                 # arg is not truncated at start
                 slice_start = 0
-                a_start = s_start - e.start
+                a_start = index - e.start
             # a is truncated at stop
-            if e.stop < s_stop:
-                slice_stop = arg.size + e.stop - s_stop - slice_start
+            if e.stop < index + arg.size:
+                slice_stop = arg.size + e.stop - (index + arg.size) - slice_start
                 a_stop = e.stop - e.start
             else:
                 slice_stop = arg.size
-                a_stop = s_stop - e.start
-            out.append((arg[slice_start:slice_stop], a_start, a_stop))
+                a_stop = index + arg.size - e.start
+            out.append(arg[slice_start:slice_stop])
 
-        out.sort(key=lambda x:x[1])
-        starts = [start for (_, start, _) in out]
-        assert len(set(starts)) == len(starts)
-        args = [expr for (expr, _, _) in out]
-
-        return ExprCompose(*args)
+        return ExprCompose(*out)
 
     # ExprMem(x, size)[:A] => ExprMem(x, a)
     # XXXX todo hum, is it safe?
@@ -553,71 +537,60 @@ def simp_slice(e_s, e):
 
 def simp_compose(e_s, e):
     "Commons simplification on ExprCompose"
-    args = merge_sliceto_slice(e.args)
+    args = merge_sliceto_slice(e)
     out = []
     # compose of compose
-    for a in args:
-        if isinstance(a[0], ExprCompose):
-            for x, start, stop in a[0].args:
-                out.append((x, start + a[1], stop + a[1]))
+    for arg in args:
+        if isinstance(arg, ExprCompose):
+            out += arg.args
         else:
-            out.append(a)
+            out.append(arg)
     args = out
     # Compose(a) with a.size = compose.size => a
-    if len(args) == 1 and args[0][1] == 0 and args[0][2] == e.size:
-        return args[0][0]
+    if len(args) == 1 and args[0].size == e.size:
+        return args[0]
 
     # {(X[z:], 0, X.size-z), (0, X.size-z, X.size)} => (X >> z)
     if (len(args) == 2 and
-        isinstance(args[1][0], ExprInt) and
-        args[1][0].arg == 0):
-        a1 = args[0]
-        a2 = args[1]
-        if (isinstance(a1[0], ExprSlice) and
-            a1[1] == 0 and
-            a1[0].stop == a1[0].arg.size and
-            a2[1] == a1[0].size and
-                a2[2] == a1[0].arg.size):
-            new_e = a1[0].arg >> ExprInt(
-                a1[0].start, a1[0].arg.size)
+        isinstance(args[1], ExprInt) and
+        int(args[1]) == 0):
+        if (isinstance(args[0], ExprSlice) and
+            args[0].stop == args[0].arg.size and
+            args[0].size + args[1].size == args[0].arg.size):
+            new_e = args[0].arg >> ExprInt(args[0].start, args[0].arg.size)
             return new_e
 
     # Compose with ExprCond with integers for src1/src2 and intergers =>
     # propagage integers
     # {XXX?(0x0,0x1)?(0x0,0x1),0,8, 0x0,8,32} => XXX?(int1, int2)
-
     ok = True
-    expr_cond = None
-    expr_ints = []
-    for i, a in enumerate(args):
-        if not is_int_or_cond_src_int(a[0]):
+    expr_cond_index = None
+    expr_ints_or_conds = []
+    for i, arg in enumerate(args):
+        if not is_int_or_cond_src_int(arg):
             ok = False
             break
-        expr_ints.append(a)
-        if isinstance(a[0], ExprCond):
-            if expr_cond is not None:
+        expr_ints_or_conds.append(arg)
+        if isinstance(arg, ExprCond):
+            if expr_cond_index is not None:
                 ok = False
-            expr_cond = i
-            cond = a[0]
+            expr_cond_index = i
+            cond = arg
 
-    if ok and expr_cond is not None:
+    if ok and expr_cond_index is not None:
         src1 = []
         src2 = []
-        for i, a in enumerate(expr_ints):
-            if i == expr_cond:
-                src1.append((a[0].src1, a[1], a[2]))
-                src2.append((a[0].src2, a[1], a[2]))
+        for i, arg in enumerate(expr_ints_or_conds):
+            if i == expr_cond_index:
+                src1.append(arg.src1)
+                src2.append(arg.src2)
             else:
-                src1.append(a)
-                src2.append(a)
-        src1 = [expr for (expr, _, _) in src1]
-        src2 = [expr for (expr, _, _) in src2]
+                src1.append(arg)
+                src2.append(arg)
         src1 = e_s.apply_simp(ExprCompose(*src1))
         src2 = e_s.apply_simp(ExprCompose(*src2))
         if isinstance(src1, ExprInt) and isinstance(src2, ExprInt):
             return ExprCond(cond.cond, src1, src2)
-    args.sort(key=lambda x:x[1])
-    args = [expr for (expr, _, _) in args]
     return ExprCompose(*args)
 
 
diff --git a/miasm2/ir/ir.py b/miasm2/ir/ir.py
index 2c6300a9..d8cccc64 100644
--- a/miasm2/ir/ir.py
+++ b/miasm2/ir/ir.py
@@ -46,7 +46,6 @@ class AssignBlock(dict):
         * if dst is an ExprSlice, expand it to affect the full Expression
         * if dst already known, sources are merged
         """
-
         if dst.size != src.size:
             raise RuntimeError(
                 "sanitycheck: args must have same size! %s" %
@@ -75,6 +74,7 @@ class AssignBlock(dict):
             expr_list = [(new_dst, new_src),
                          (new_dst, self[new_dst])]
             # Find collision
+            print 'FIND COLISION'
             e_colision = reduce(lambda x, y: x.union(y),
                                 (self.get_modified_slice(dst, src)
                                  for (dst, src) in expr_list),
@@ -109,17 +109,16 @@ class AssignBlock(dict):
     def get_modified_slice(dst, src):
         """Return an Expr list of extra expressions needed during the
         object instanciation"""
-
         if not isinstance(src, m2_expr.ExprCompose):
             raise ValueError("Get mod slice not on expraff slice", str(self))
         modified_s = []
-        for arg in src.args:
-            if (not isinstance(arg[0], m2_expr.ExprSlice) or
-                    arg[0].arg != dst or
-                    arg[1] != arg[0].start or
-                    arg[2] != arg[0].stop):
+        for index, arg in src.iter_args():
+            if not (isinstance(arg, m2_expr.ExprSlice) and
+                    arg.arg == dst and
+                    index == arg.start and
+                    index+arg.size == arg.stop):
                 # If x is not the initial expression
-                modified_s.append(arg)
+                modified_s.append((arg, index, index+arg.size))
         return modified_s
 
     def get_w(self):
diff --git a/miasm2/ir/symbexec.py b/miasm2/ir/symbexec.py
index 65515c64..db3eacdc 100644
--- a/miasm2/ir/symbexec.py
+++ b/miasm2/ir/symbexec.py
@@ -229,9 +229,8 @@ class symbexec(object):
             ret = m2_expr.ExprOp(expr.op, *args)
         elif isinstance(expr, m2_expr.ExprCompose):
             args = []
-            for (arg, start, stop) in expr.args:
-                arg = self.apply_expr_on_state_visit_cache(arg, state, cache, level+1)
-                args.append(arg)
+            for arg in expr.args:
+                args.append(self.apply_expr_on_state_visit_cache(arg, state, cache, level+1))
             ret = m2_expr.ExprCompose(*args)
         else:
             raise TypeError("Unknown expr type")
@@ -378,7 +377,6 @@ class symbexec(object):
         """
         pool_out = {}
         eval_cache = {}
-
         for dst, src in assignblk.iteritems():
             src = self.eval_expr(src, eval_cache)
             if isinstance(dst, m2_expr.ExprMem):
diff --git a/miasm2/ir/translators/C.py b/miasm2/ir/translators/C.py
index 340fbfec..57859f9c 100644
--- a/miasm2/ir/translators/C.py
+++ b/miasm2/ir/translators/C.py
@@ -145,11 +145,11 @@ class TranslatorC(Translator):
         out = []
         # XXX check mask for 64 bit & 32 bit compat
         dst_cast = "uint%d_t" % expr.size
-        for x in expr.args:
+        for index, arg in expr.iter_args():
             out.append("(((%s)(%s & 0x%X)) << %d)" % (dst_cast,
-                                                      self.from_expr(x[0]),
-                                                      (1 << (x[2] - x[1])) - 1,
-                                                      x[1]))
+                                                      self.from_expr(arg),
+                                                      (1 << arg.size) - 1,
+                                                      index))
         out = ' | '.join(out)
         return '(' + out + ')'
 
diff --git a/miasm2/ir/translators/miasm.py b/miasm2/ir/translators/miasm.py
index 515148ee..b390eb51 100644
--- a/miasm2/ir/translators/miasm.py
+++ b/miasm2/ir/translators/miasm.py
@@ -27,8 +27,7 @@ class TranslatorMiasm(Translator):
                                    ", ".join(map(self.from_expr, expr.args)))
 
     def from_ExprCompose(self, expr):
-        args = ["%s" % self.from_expr(arg)
-                for arg, _, _ in expr.args]
+        args = ["%s" % self.from_expr(arg) for arg in expr.args]
         return "ExprCompose(%s)" % ", ".join(args)
 
     def from_ExprAff(self, expr):
diff --git a/miasm2/ir/translators/python.py b/miasm2/ir/translators/python.py
index f745d2df..c06d865c 100644
--- a/miasm2/ir/translators/python.py
+++ b/miasm2/ir/translators/python.py
@@ -31,10 +31,10 @@ class TranslatorPython(Translator):
 
     def from_ExprCompose(self, expr):
         out = []
-        for subexpr, start, stop in expr.args:
-            out.append("((%s & 0x%x) << %d)" % (self.from_expr(subexpr),
-                                                 (1 << (stop - start)) - 1,
-                                                 start))
+        for index, arg in expr.iter_args():
+            out.append("((%s & 0x%x) << %d)" % (self.from_expr(arg),
+                                                 (1 << arg.size) - 1,
+                                                 index))
         return "(%s)" % ' | '.join(out)
 
     def from_ExprCond(self, expr):
diff --git a/miasm2/ir/translators/smt2.py b/miasm2/ir/translators/smt2.py
index 5bffd7f2..5d5fb26b 100644
--- a/miasm2/ir/translators/smt2.py
+++ b/miasm2/ir/translators/smt2.py
@@ -163,10 +163,8 @@ class TranslatorSMT2(Translator):
 
     def from_ExprCompose(self, expr):
         res = None
-        args = sorted(expr.args, key=operator.itemgetter(2))  # sort by start off
-        for subexpr, start, stop in args:
-            sube = self.from_expr(subexpr)
-            e = bv_extract(stop-start-1, 0, sube)
+        for arg in expr.args:
+            e = bv_extract(arg.size-1, 0, self.from_expr(arg))
             if res:
                 res = bv_concat(e, res)
             else:
diff --git a/miasm2/ir/translators/z3_ir.py b/miasm2/ir/translators/z3_ir.py
index e0460cc4..ccb14b4f 100644
--- a/miasm2/ir/translators/z3_ir.py
+++ b/miasm2/ir/translators/z3_ir.py
@@ -137,10 +137,8 @@ class TranslatorZ3(Translator):
 
     def from_ExprCompose(self, expr):
         res = None
-        args = sorted(expr.args, key=operator.itemgetter(2)) # sort by start off
-        for subexpr, start, stop in args:
-            sube = self.from_expr(subexpr)
-            e = z3.Extract(stop-start-1, 0, sube)
+        for arg in expr.args:
+            e = z3.Extract(arg.size-1, 0, self.from_expr(arg))
             if res != None:
                 res = z3.Concat(e, res)
             else: