예제 #1
0
    def get_pred(self):
        if self.is_ninf():
            return copy.deepcopy(self)
        if self.is_pzero():
            return Float('-0',ne=self.ne,ns=self.ns).get_pred()
        bv_str = self.get_bv_str()
        #print(bv_str)
        sign = bv_str[0]
        if sign == '0':
            succ = int(bv_str[1:],2) - 1
            return Float(val=z3.simplify(z3.fpBVToFP(z3.Int2BV(z3.IntVal(succ),num_bits = self.ns + self.ne),z3.FPSort(self.ne,self.ns))),ne=self.ne, ns=self.ns)

        else:
            succ = int(bv_str[1:],2) + 1
            return -Float(val=z3.simplify(z3.fpBVToFP(z3.Int2BV(z3.IntVal(succ),num_bits = self.ns + self.ne),z3.FPSort(self.ne,self.ns))),ne=self.ne, ns=self.ns)
예제 #2
0
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef:
    if z3.is_bv(val):
        szdiff = size - val.size()

        if szdiff > 0:
            if signext:
                result = z3.SignExt(szdiff, val)
            else:
                result = z3.ZeroExt(szdiff, val)
        elif szdiff < 0:
            result = z3.Extract(size - 1, 0, val)
        else:
            result = val
    elif type(val) == int:
        result = z3.BitVecVal(val, size)
    elif z3.is_int(val):
        result = z3.Int2BV(val, size)
    elif z3.is_fp(val):
        # changing up this logic to align with r2ghidra impl
        result = z3.fpToIEEEBV(val)
        #result = val
    else:
        result = z3.BitVecVal(val, size)

    #return z3.simplify(result)
    return result
예제 #3
0
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef:
    if z3.is_bv(val):
        szdiff = size-val.size()
        if szdiff == 0:
            result = val
        elif szdiff > 0:
            if signext:
                result = z3.SignExt(szdiff, val)
            else:
                result = z3.ZeroExt(szdiff, val)
        elif szdiff < 0:
            result = z3.Extract(size-1, 0, val)

    elif isinstance(val, int):
        result = z3.BitVecVal(val, size)
    elif z3.is_int(val):
        result = z3.Int2BV(val, size)
    elif z3.is_fp(val):
        result = z3.fpToIEEEBV(val)
    else:
        result = z3.BitVecVal(val, size)

    if not z3.is_bv_value(result):
        return z3.simplify(result)
    else:
        return result
예제 #4
0
    def _binop_dunder_operation(self,
                                op: str,
                                op_callback,
                                reflected=False,
                                other: nodes.Const = None):
        other_defaults = other.defaults if isinstance(other, Z3Proxy) else {}
        left = self.value
        right = utilities.make_z3_const(utilities.strip_constant_node(other))
        extras = []
        if op in ("&", ">>", "<<"):
            # cast left and right to BitVector for bit operation.
            left, right = z3.Int2BV(left, 64), z3.Int2BV(right, 64)
        elif op in ("/", "//"):
            # special handling divide, due to we have "//" operation in py2 protocol, and
            # it's incompatible with z3
            if op == "//":
                # convert result to floor.
                MANAGER.logger.warning(
                    "Z3",
                    "Floor division (//) is not supported and will cast to (/), for node: {}",
                    repr(self))
            extras.append(right != 0)
            op_callback = lambda x, y: x / y

        elif op == "%":
            # casting left and right to int before doing modulo
            if not z3.is_int(left):
                left = z3.ToInt(left)
            if not z3.is_int(right):
                right = z3.ToInt(right)
            extras.append(right != 0)
        try:
            if not reflected:
                result = op_callback(left, right)
            else:
                result = op_callback(right, left)
            res = inference.InferenceResult(Z3Proxy.init_expr(
                result, {
                    **self.defaults,
                    **other_defaults
                }),
                                            status=True)
            res.z3_assumptions |= set(extras)
            return res
        except (z3.Z3Exception, TypeError):
            return inference.InferenceResult.load_result(nodes.Uninferable())
예제 #5
0
 def __cast_to_bits__(self, reference):
     if isinstance(reference, z3.ArithRef) or isinstance(
             reference, z3.IntNumRef):
         return z3.Int2BV(reference, self.longLength)
     elif isinstance(reference, z3.BoolRef):
         return z3.If(reference, 1, 0)
     else:
         return reference
예제 #6
0
def prepare(val):
    if z3.is_bv(val):
        #print(val)
        szdiff = SIZE - val.size()
        #print(szdiff, val.size())
        if szdiff > 0:
            return z3.ZeroExt(szdiff, val)
        else:
            return val
    elif z3.is_int(val):
        return z3.Int2BV(val, SIZE)
    else:
        return z3.BitVecVal(val, SIZE)
예제 #7
0
파일: util.py 프로젝트: zwegner/x86-sat
def extend(value, width, signed=None):
    if not is_z3(value):
        return value
    # XXX range check
    if not z3.is_bv(value):
        value = z3.Int2BV(value, width)
    assert value.size() > 0
    diff = try_simplify(width - value.size())
    if diff > 0:
        if signed is None:
            # XXX default to unsigned
            signed = False
        if signed:
            return z3.SignExt(diff, value)
        else:
            return z3.ZeroExt(diff, value)
    return value
예제 #8
0
    def val_to_register_bv(self, reg: Dict, val):
        new_val = val

        if isinstance(val, int):
            new_val = z3.BitVecVal(val, reg["size"])

        elif z3.is_int(val):
            new_val = z3.Int2BV(val, reg["size"])

        elif z3.is_bv(val):
            if val.size() > reg["size"]:
                new_val = z3.Extract(reg["size"] - 1, 0, val)
            elif val.size() < reg["size"]:
                new_val = z3.ZeroExt(reg["size"] - val.size(), val)

        else:
            raise ESILArgumentException("%s %s" % (reg, val))

        return new_val
예제 #9
0
    def proc_apply(self, expr, state):
        f = self.context.reduce(expr['func'])
        args = expr['args']
        if f['what'] == 'expr:special':
            if f['id'] == 'gmap_lookup':
                state, k = self.proc(args[0], state)
                state, m = self.proc(args[1], state)
                return state, m[k]
            elif f['id'] == 'map_insert':
                state, k = self.proc(args[0], state)
                state, v = self.proc(args[1], state)
                state, m = self.proc(args[2], state)

                rangesort = m.range()
                vsome = constructor_by_name(rangesort, "Some")(v)

                return state, z3.Store(m, k, vsome)
            elif f['id'] == 'len_buf':
                state, buf = self.proc(args[0], state)
                return state, z3.Int2BV(z3.Length(buf), 64)
            elif f['id'] == 'resize_buf':
                state, newlen = self.proc(args[0], state)
                state, buf = self.proc(args[1], state)
                ## XXX should be of length newlen, not empty..
                return state, z3.Empty(buf.sort())
            elif f['id'] == 'uint64_gt':
                state, a0 = self.proc(args[0], state)
                state, a1 = self.proc(args[1], state)
                return state, z3.If(a0 > a1,
                                    self.bool_sort.constructor(0)(),
                                    self.bool_sort.constructor(1)())
            elif f['id'] == 'eqDec_time':
                state, a0 = self.proc(args[0], state)
                state, a1 = self.proc(args[1], state)
                return state, z3.If(a0 == a1,
                                    self.sumbool_sort.constructor(0)(),
                                    self.sumbool_sort.constructor(1)())
            else:
                raise Exception('unknown special function', f['id'])
        else:
            print expr
            raise Exception('unknown apply on', f['what'])
def opcode_exp(opcode_data1, opcode_data2):

    if not is_z3_express(opcode_data1) and not is_z3_express(opcode_data2):
        op1 = format_to_int(opcode_data1)
        op2 = format_to_int(opcode_data2)
        result = op1**op2
        return z3.BitVecVal(result, 256)

    size = 0
    if is_z3_express(
            opcode_data1) or opcode_data1.__class__ == z3.z3.BitVecNumRef:
        size = opcode_data1.size()
        opcode_data1 = z3.BV2Int(opcode_data1)

    if is_z3_express(
            opcode_data2) or opcode_data1.__class__ == z3.z3.BitVecNumRef:
        if opcode_data2.size() > size:
            size = opcode_data2.size()
        opcode_data2 = z3.BV2Int(opcode_data2)

    return (z3.simplify(z3.Int2BV(opcode_data1**opcode_data2, size)))
예제 #11
0
    def val_to_register_bv(self, reg: Dict, val):
        new_val = val

        if type(val) == int:
            new_val = z3.BitVecVal(val, reg["size"])

        elif z3.is_int(val):
            new_val = z3.Int2BV(val, reg["size"])

        elif z3.is_bv(val):
            if val.size() > reg["size"]:
                new_val = z3.Extract(reg["size"] - 1, 0, val)
            elif val.size() < reg["size"]:
                new_val = z3.ZeroExt(reg["size"] - val.size(), val)
            else:
                new_reg = val

        else:
            raise ESILArgumentException

        return new_val
예제 #12
0
    def cast(self, value, is_type, to_type):
        if is_type is Types.STRING and isinstance(to_type,
                                                  z3.z3.DatatypeSortRef):
            # the value is a string and it should be cast to a datatyperef
            # (i.e. an enum-type), just return the value because we can deal with it
            return value

        value_is_int = isinstance(value, int)
        value_is_float = isinstance(value, float)

        if is_type is to_type:  # already correct type, just return the value
            return value
            """ INT <---> INTEGER """
        elif is_type is Types.INT and to_type is Types.INTEGER:
            if value_is_int or value_is_float:
                return value  # this happens if it is an int numeral (e.g. 2)
            else:
                return z3.BV2Int(value)
        elif is_type is Types.INTEGER and to_type is Types.INT:
            if value_is_int or value_is_float:
                return value
            else:
                return z3.Int2BV(value, 32)
            """ INT <---> FLOAT """
        elif is_type is Types.FLOAT and to_type is Types.INT:
            if value_is_float:
                return value  # this happens if it is a float numeral (e.g. 3.14)
            else:
                return z3.fpToSBV(z3.RNE(), value, z3.BitVecSort(32))
        elif is_type is Types.INT and to_type is Types.FLOAT:
            if value_is_int:
                return value
            else:
                return z3.fpSignedToFP(z3.RNE(), value, z3.Float32())
            """ INTEGER <---> FLOAT """
        elif is_type is Types.FLOAT and to_type is Types.INTEGER:
            if value_is_float:
                return value  # this happens if it is a float numeral (e.g. 3.14)
            else:
                return self.cast(self.cast(value, Types.FLOAT, Types.INT),
                                 Types.INT, Types.INTEGER)
        elif is_type is Types.INTEGER and to_type is Types.FLOAT:
            if value_is_int:
                return value
            else:
                return self.cast(self.cast(value, Types.INTEGER, Types.INT),
                                 Types.INT, Types.FLOAT)
            """ from REAL """
        elif is_type is Types.REAL and to_type is Types.INTEGER:
            if value_is_float:
                return value
            else:
                return z3.ToInt(value)
        elif is_type is Types.REAL and to_type is Types.INT:
            return self.cast(self.cast(value, Types.REAL, Types.INTEGER),
                             Types.INTEGER, Types.INT)
        elif is_type is Types.REAL and to_type is Types.FLOAT:
            """
            Rounding modes: probably should make these parameterizable!
            roundNearestTiesToEven ... RNE() = default
            roundNearestTiesToAway ... RNA()
            roundTowardPositive ...... RTP()
            roundTowardNegative ...... RTN()
            roundTowardZero .......... RTZ()
            """
            if value_is_int or value_is_float:  # int numeral
                return value
            else:
                return z3.fpRealToFP(z3.RNE(), value, z3.Float32())
            """ to REAL """
        elif is_type is Types.INT and to_type is Types.REAL:
            if value_is_int or value_is_float:  # int numeral
                return value
            else:
                return z3.ToReal(self.cast(value, Types.INT, Types.INTEGER))
        elif is_type is Types.INTEGER and to_type is Types.REAL:
            if value_is_int or value_is_float:  # int numeral
                return value
            else:
                return z3.ToReal(value)
        elif is_type is Types.FLOAT and to_type is Types.REAL:
            if value_is_int or value_is_float:
                return value  # this happens if it is a float numeral (e.g. 3.14)
            else:
                return z3.fpToReal(value)
            """ FROM BOOL conversions """
        elif is_type is Types.BOOL and to_type is Types.INT:
            return z3.If(value, z3.BitVecVal(1, 32), z3.BitVecVal(0, 32))
        elif is_type is Types.BOOL and to_type is Types.INTEGER:
            return z3.If(value, 1, 0)
        elif is_type is Types.BOOL and to_type is Types.REAL:
            return z3.If(value, 1.0, 0.0)
        elif is_type is Types.BOOL and to_type is Types.FLOAT:
            return z3.If(value, z3.FPVal(1.0, z3.Float32()),
                         z3.FPVal(0.0, z3.Float32()))
            """ TO BOOL conversions """
        elif is_type is Types.INT and to_type is Types.BOOL:
            return value == 1
        elif is_type is Types.INTEGER and to_type is Types.BOOL:
            return value == 1
        elif is_type is Types.REAL and to_type is Types.BOOL:
            return value == 1
        elif is_type is Types.FLOAT and to_type is Types.BOOL:
            return value == 1

        raise TypeError(f"Don't know how to cast from {is_type} to {to_type}!")
예제 #13
0
    def proc_apply(self, expr, state):
        f = self.context.reduce(expr['func'])
        args = expr['args']

        if f['what'] == 'expr:special':
            # for converting Z to u32
            if f['id'] == 'u3' or f['id'] == 'u2':
                arg = args[0]
                # be able to distinguish between Z->u32 and Z->u64
                if f['id'] == 'u3':
                    arg['name'] = 'u32'
                else:
                    arg['name'] = 'u64'
                state, val = self.proc(arg, state)
                return state, z3.Const(anon(), val)

            elif f['id'] == 'gtb':
                arg0 = args[0]['cases'][0]['body']['args'][0]
                nstate, arg1 = self.proc(
                    args[1]['cases'][0]['body']['args'][0], state)
                return nstate, z3.If(arg0 > arg1,
                                     self.bool_sort.constructor(0)(),
                                     self.bool_sort.constructor(1)())

            elif f['id'] == 'gmap_lookup':
                state, k = self.proc(args[0], state)
                state, m = self.proc(args[1], state)
                return state, m[k]

            elif f['id'] == 'map_insert':
                state, k = self.proc(args[0], state)
                state, v = self.proc(args[1], state)
                state, m = self.proc(args[2], state)

                rangesort = m.range()
                vsome = constructor_by_name(rangesort, "Some")(v)

                return state, z3.Store(m, k, vsome)

            elif f['id'] == 'reads':
                return state, state

            elif f['id'] == 'modify':
                _, newstate = self.proc(args[0]['body'], state)
                return newstate, self.unit_tt

            elif f['id'] == 'ret':
                state, res = self.proc(args[0], state)
                return state, res

            elif f['id'] == 'len_buf':
                state, buf = self.proc(args[0], state)
                return state, z3.Int2BV(z3.Length(buf), 64)

            elif f['id'] == 'resize_buf':
                state, newlen = self.proc(args[0], state)
                state, buf = self.proc(args[1], state)
                ## XXX should be of length newlen, not empty..
                return state, z3.Empty(buf.sort())

            elif f['id'] == 'eqDec_time':
                state, a0 = self.proc(args[0], state)
                state, a1 = self.proc(args[1], state)
                return state, z3.If(a0 == a1,
                                    self.sumbool_sort.constructor(0)(),
                                    self.sumbool_sort.constructor(1)())

            elif f['id'] == 'time_ge':
                state, a0 = self.proc(args[0], state)
                state, a1 = self.proc(args[1], state)
                # constructor 0 is true, 1 is false
                return state, z3.If(a0 >= a1,
                                    self.bool_sort.constructor(0)(),
                                    self.bool_sort.constructor(1)())

            elif f['id'] == 'symAssert':
                state, a = self.proc(args[0], state)
                return state, z3.And(a == self.bool_sort.constructor(0)())

            else:
                raise Exception('unknown special function', f['id'])
        else:
            raise Exception('unknown apply on', f['what'])
예제 #14
0
def _cmp(cmp, a, b, **kwargs):
    [a, b, width, signed] = match_types(a, b)
    a = z3.BV2Int(a, is_signed=signed)
    b = z3.BV2Int(b, is_signed=signed)
    return z3.Int2BV(z3.If(cmp(a, b), a, b), width)
예제 #15
0
 def _mk_pzero(self):
     self.__dict__ = copy.deepcopy(Float(val=z3.simplify(z3.fpBVToFP(z3.Int2BV(z3.IntVal(0),num_bits = self.ns + self.ne),z3.FPSort(self.ne,self.ns))),ne=self.ne, ns=self.ns).__dict__)
예제 #16
0
 def _mk_nan(self):
     bv = '0' + ('1' * self.ne) + ('1' * (self.ns -1))
     val = int(bv,2)
     self.__dict__ = copy.deepcopy(Float(val=z3.simplify(z3.fpBVToFP(z3.Int2BV(z3.IntVal(val),num_bits = self.ns + self.ne),z3.FPSort(self.ne,self.ns))),ne=self.ne, ns=self.ns).__dict__)
예제 #17
0
def interp(tree, lookup, z3_mode):
    """Evaluate the arithmetic expression.

    Pass a tree as a Lark `Tree` object for the parsed expression. For
    `lookup`, provide a function for mapping variable names to values.
    """

    op = tree.data
    if op in ('add', 'sub', 'mul', 'div', 'shl', 'shr'):  # Binary operators.
        lhs = interp(tree.children[0], lookup, z3_mode)
        rhs = interp(tree.children[1], lookup, z3_mode)
        if op == 'add':
            return lhs + rhs
        elif op == 'sub':
            return lhs - rhs
        elif op == 'mul':
            return lhs * rhs
        elif op == 'div':
            return lhs / rhs
        elif op == 'shl':
            return lhs << rhs
        elif op == 'shr':
            return lhs >> rhs
    elif op == 'neg':  # Negation.
        sub = interp(tree.children[0], lookup, z3_mode)
        return -sub
    elif op == 'int':  # Literal number.
        if z3_mode:
            return z3.BitVecVal(int(tree.children[0]), 32)
        else:
            return int(tree.children[0])
    elif op == 'float':  # Literal number.
        if z3_mode:
            return z3.BitVecVal(float(tree.children[0]), 32)
        else:
            return float(tree.children[0])
    elif op == 'var':  # Variable lookup.
        return lookup(tree.children[0])
    elif op == 'if':  # Conditional.
        cond = interp(tree.children[0], lookup, z3_mode)
        true = interp(tree.children[1], lookup, z3_mode)
        false = interp(tree.children[2], lookup, z3_mode)
        return (cond != 0) * true + (cond == 0) * false
    elif op == "intcast":
        child = interp(tree.children[0], lookup, z3_mode)
        if z3_mode:
            return z3.BV2Int(child)
        else:
            return int(child)
    elif op == "floatcast":
        child = interp(tree.children[0], lookup, z3_mode)
        if z3_mode:
            return z3.fpBVToFP(child, z3.Float32())
        else:
            return float(child)
    elif op == "int2bv":
        child = interp(tree.children[0], lookup, z3_mode)
        if z3_mode:
            return z3.Int2BV(child, 32)
        else:
            return child
    elif op == "float2bv":
        child = interp(tree.children[0], lookup, z3_mode)
        if z3_mode:
            return z3.fpToIEEEBV(child)
        else:
            return child