about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/expression/simplifications_common.py21
-rw-r--r--miasm2/ir/translators/z3_ir.py12
-rw-r--r--miasm2/jitter/vm_mngr.h2
-rw-r--r--test/expression/simplifications.py10
4 files changed, 40 insertions, 5 deletions
diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py
index ccb97cb3..a1301cba 100644
--- a/miasm2/expression/simplifications_common.py
+++ b/miasm2/expression/simplifications_common.py
@@ -40,13 +40,26 @@ def simp_cst_propagation(e_s, expr):
             elif op_name == '|':
                 out = int1.arg | int2.arg
             elif op_name == '>>':
-                out = int1.arg >> int2.arg
+                if int(int2) > int1.size:
+                    out = 0
+                else:
+                    out = int1.arg >> int2.arg
             elif op_name == '<<':
-                out = int1.arg << int2.arg
+                if int(int2) > int1.size:
+                    out = 0
+                else:
+                    out = int1.arg << int2.arg
             elif op_name == 'a>>':
                 tmp1 = mod_size2int[int1.arg.size](int1.arg)
                 tmp2 = mod_size2uint[int2.arg.size](int2.arg)
-                out = mod_size2uint[int1.arg.size](tmp1 >> tmp2)
+                if tmp2 > int1.size:
+                    is_signed = int(int1) & (1 << (int1.size - 1))
+                    if is_signed:
+                        out = -1
+                    else:
+                        out = 0
+                else:
+                    out = mod_size2uint[int1.arg.size](tmp1 >> tmp2)
             elif op_name == '>>>':
                 shifter = int2.arg % int2.size
                 out = (int1.arg >> shifter) | (int1.arg << (int2.size - shifter))
@@ -539,7 +552,7 @@ def simp_compose(e_s, expr):
         nxt = args[i + 1]
         if arg.is_mem() and nxt.is_mem():
             gap = e_s(nxt.arg - arg.arg)
-            if gap.is_int() 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.arg,
                                           arg.size + nxt.size)] + args[i + 2:]
                 return ExprCompose(*args)
diff --git a/miasm2/ir/translators/z3_ir.py b/miasm2/ir/translators/z3_ir.py
index d33764fb..74bdd79c 100644
--- a/miasm2/ir/translators/z3_ir.py
+++ b/miasm2/ir/translators/z3_ir.py
@@ -1,7 +1,9 @@
+import imp
 import logging
 import operator
 
-import z3
+# Raise an ImportError if z3 is not available WITHOUT actually importing it
+imp.find_module("z3")
 
 from miasm2.core.asmblock import AsmLabel
 from miasm2.ir.translators.translator import Translator
@@ -31,6 +33,10 @@ class Z3Mem(object):
         @name: name of memory Arrays generated. They will be named
             name+str(address size) (for example mem32, mem16...).
         """
+        # Import z3 only on demand
+        global z3
+        import z3
+
         if endianness not in ['<', '>']:
             raise ValueError("Endianness should be '>' (big) or '<' (little)")
         self.endianness = endianness
@@ -114,6 +120,10 @@ class TranslatorZ3(Translator):
         """Instance a Z3 translator
         @endianness: (optional) memory endianness
         """
+        # Import z3 only on demand
+        global z3
+        import z3
+
         super(TranslatorZ3, self).__init__(**kwargs)
         self._mem = Z3Mem(endianness)
 
diff --git a/miasm2/jitter/vm_mngr.h b/miasm2/jitter/vm_mngr.h
index 71ecc246..d114d8f0 100644
--- a/miasm2/jitter/vm_mngr.h
+++ b/miasm2/jitter/vm_mngr.h
@@ -217,6 +217,8 @@ unsigned int umul16_hi(unsigned short a, unsigned short b);
 uint64_t rot_left(uint64_t size, uint64_t a, uint64_t b);
 uint64_t rot_right(uint64_t size, uint64_t a, uint64_t b);
 
+unsigned int x86_bsr(uint64_t size, uint64_t src);
+unsigned int x86_bsf(uint64_t size, uint64_t src);
 
 #define UDIV(sizeA)						\
 	uint ## sizeA ## _t udiv ## sizeA (vm_cpu_t* vmcpu, uint ## sizeA ## _t a, uint ## sizeA ## _t b) \
diff --git a/test/expression/simplifications.py b/test/expression/simplifications.py
index c6dabfe8..3e2e5177 100644
--- a/test/expression/simplifications.py
+++ b/test/expression/simplifications.py
@@ -411,6 +411,16 @@ to_test = [(ExprInt(1, 32) - ExprInt(1, 32), ExprInt(0, 32)),
     (a >> b >> c, a >> b >> c), # Left unmodified
     (a >> b_msb_null >> c_msb_null,
      a >> (b_msb_null + c_msb_null)),
+
+    # Degenerated case from fuzzing, which had previously raised bugs
+    (ExprCompose(ExprInt(0x7, 3), ExprMem(ExprInt(0x39E21, 19), 1), ExprMem(ExprInt(0x39E21, 19), 1)),
+     ExprCompose(ExprInt(0x7, 3), ExprMem(ExprInt(0x39E21, 19), 1), ExprMem(ExprInt(0x39E21, 19), 1))),
+    (ExprOp('>>', ExprInt(0x5E580475, 92), ExprInt(0x7D800000000000000331720, 92)),
+     ExprInt(0x0, 92)),
+    (ExprOp('a>>', ExprInt(0x5E580475, 92), ExprInt(0x7D800000000000000331720, 92)),
+     ExprInt(0x0, 92)),
+    (ExprOp('a>>', ExprInt(-0x5E580475, 92), ExprInt(0x7D800000000000000331720, 92)),
+     ExprInt(-1, 92)),
 ]
 
 for e_input, e_check in to_test: