Beispiel #1
0
    def _abstract_internal(self, ctx, ast, split_on=None):
        h = self._z3_ast_hash(ctx, ast)
        try:
            return self._ast_cache[h]
        except KeyError:
            pass

        decl = z3.Z3_get_app_decl(ctx, ast)
        decl_num = z3.Z3_get_decl_kind(ctx, decl)
        z3_sort = z3.Z3_get_sort(ctx, ast)

        if decl_num not in z3_op_nums:
            raise ClaripyError("unknown decl kind %d" % decl_num)
        if z3_op_nums[decl_num] not in op_map:
            raise ClaripyError("unknown decl op %s" % z3_op_nums[decl_num])
        op_name = op_map[z3_op_nums[decl_num]]

        num_args = z3.Z3_get_app_num_args(ctx, ast)
        split_on = self._split_on if split_on is None else split_on
        new_split_on = split_on if op_name in split_on else set()
        children = [
            self._abstract_internal(ctx, z3.Z3_get_app_arg(ctx, ast, i),
                                    new_split_on) for i in range(num_args)
        ]

        append_children = True

        if op_name == 'True':
            return BoolV(True)
        elif op_name == 'False':
            return BoolV(False)
        elif op_name.startswith('RM_'):
            return RM.from_name(op_name)
        elif op_name == 'BitVecVal':
            bv_size = z3.Z3_get_bv_sort_size(ctx, z3_sort)
            if z3.Z3_get_numeral_uint64(ctx, ast, self._c_uint64_p):
                return BVV(self._c_uint64_p.contents.value, bv_size)
            else:
                bv_num = int(z3.Z3_get_numeral_string(ctx, ast))
                return BVV(bv_num, bv_size)
        elif op_name in ('FPVal', 'MinusZero', 'MinusInf', 'PlusZero',
                         'PlusInf', 'NaN'):
            ebits = z3.Z3_fpa_get_ebits(ctx, z3_sort)
            sbits = z3.Z3_fpa_get_sbits(ctx, z3_sort)
            sort = FSort.from_params(ebits, sbits)
            val = self._abstract_fp_val(ctx, ast, op_name)
            return FPV(val, sort)

        elif op_name == 'UNINTERPRETED' and num_args == 0:  # symbolic value
            symbol_name = z3.Z3_get_symbol_string(
                ctx, z3.Z3_get_decl_name(ctx, decl))
            symbol_ty = z3.Z3_get_sort_kind(ctx, z3_sort)

            if symbol_ty == z3.Z3_BV_SORT:
                bv_size = z3.Z3_get_bv_sort_size(ctx, z3_sort)
                return BV('BVS',
                          (symbol_name, None, None, None, False, False, None),
                          length=bv_size,
                          variables={symbol_name},
                          symbolic=True)
            elif symbol_ty == z3.Z3_FLOATING_POINT_SORT:
                ebits = z3.Z3_fpa_get_ebits(ctx, z3_sort)
                sbits = z3.Z3_fpa_get_sbits(ctx, z3_sort)
                sort = FSort.from_params(ebits, sbits)
                return FP('FPS', (symbol_name, sort),
                          variables={symbol_name},
                          symbolic=True,
                          length=sort.length)
            else:
                raise BackendError("Unknown z3 term type %d...?" % symbol_ty)

        elif op_name == 'UNINTERPRETED':
            mystery_name = z3.Z3_get_symbol_string(
                ctx, z3.Z3_get_decl_name(ctx, decl))
            args = []

            #
            # TODO: DEPRECATED: remove the following after some reasonable amount of time.
            #

            if mystery_name == 'bvsmod_i':
                l.error(
                    "Your Z3 is out of date. Please update angr-only-z3-custom or future releases of claripy will fail."
                )
                op_name = '__mod__'
                decl_num = z3.Z3_OP_BSMOD
            elif mystery_name == 'bvsdiv_i':
                l.error(
                    "Your Z3 is out of date. Please update angr-only-z3-custom or future releases of claripy will fail."
                )
                op_name = 'SDiv'
                decl_num = z3.Z3_OP_BSDIV
            else:
                l.error(
                    "Mystery operation %s in BackendZ3._abstract_internal. Please report this.",
                    mystery_name)
        elif op_name == 'Extract':
            hi = z3.Z3_get_decl_int_parameter(ctx, decl, 0)
            lo = z3.Z3_get_decl_int_parameter(ctx, decl, 1)
            args = [hi, lo]
        elif op_name in ('SignExt', 'ZeroExt'):
            num = z3.Z3_get_decl_int_parameter(ctx, decl, 0)
            args = [num]
        elif op_name in ('fpToFP', 'fpToFPSigned'):
            exp = z3.Z3_fpa_get_ebits(ctx, z3_sort)
            mantissa = z3.Z3_fpa_get_sbits(ctx, z3_sort)
            sort = FSort.from_params(exp, mantissa)
            args = children + [sort]
            append_children = False
        elif op_name in ('fpToSBV', 'fpToUBV'):
            # uuuuuugggggghhhhhh
            bv_size = z3.Z3_get_bv_sort_size(ctx, z3_sort)
            args = children + [bv_size]
            append_children = False
        else:
            args = []

        if append_children:
            args.extend(children)

        # hmm.... honestly not sure what to do here
        result_ty = op_type_map[z3_op_nums[decl_num]]
        ty = type(args[-1])

        if type(result_ty) is str:
            err = "Unknown Z3 error in abstraction (result_ty == '%s'). Update your version of Z3, and, if the problem persists, open a claripy issue." % result_ty
            l.error(err)
            raise BackendError(err)

        if op_name == 'If':
            # If is polymorphic and thus must be handled specially
            ty = type(args[1])

            a = ty('If', tuple(args), length=args[1].length)
        elif hasattr(ty, op_name) or hasattr(_all_operations, op_name):
            op = getattr(ty if hasattr(ty, op_name) else _all_operations,
                         op_name)
            if op.calc_length is not None:
                length = op.calc_length(*args)
                a = result_ty(op_name, tuple(args), length=length)
            else:
                a = result_ty(op_name, tuple(args))
        else:
            a = result_ty(op_name, tuple(args))

        self._ast_cache[h] = a
        return a
Beispiel #2
0
    def _abstract_internal(self, ctx, ast, split_on=None):
        h = self._z3_ast_hash(ctx, ast)
        try:
            return self._ast_cache[h]
        except KeyError:
            pass

        decl = z3.Z3_get_app_decl(ctx, ast)
        decl_num = z3.Z3_get_decl_kind(ctx, decl)
        z3_sort = z3.Z3_get_sort(ctx, ast)

        if decl_num not in z3_op_nums:
            raise ClaripyError("unknown decl kind %d" % decl_num)
        if z3_op_nums[decl_num] not in op_map:
            raise ClaripyError("unknown decl op %s" % z3_op_nums[decl_num])
        op_name = op_map[z3_op_nums[decl_num]]

        num_args = z3.Z3_get_app_num_args(ctx, ast)
        split_on = self._split_on if split_on is None else split_on
        new_split_on = split_on if op_name in split_on else set()
        children = [ self._abstract_internal(ctx, z3.Z3_get_app_arg(ctx, ast, i), new_split_on) for i in range(num_args) ]

        append_children = True

        if op_name == 'True':
            return BoolI(True)
        elif op_name == 'False':
            return BoolI(False)
        elif op_name.startswith('RM_'):
            return RM.from_name(op_name)
        elif op_name == 'BitVecVal':
            bv_num = long(z3.Z3_get_numeral_string(ctx, ast))
            bv_size = z3.Z3_get_bv_sort_size(ctx, z3_sort)
            return BVI(NativeBVV(bv_num, bv_size), length=bv_size)
        elif op_name == 'FPVal':
            # this is really imprecise
            fp_mantissa = float(z3.Z3_fpa_get_numeral_significand_string(ctx, ast))
            fp_exp = long(z3.Z3_fpa_get_numeral_exponent_string(ctx, ast))
            value = fp_mantissa * (2 ** fp_exp)

            ebits = z3.Z3_fpa_get_ebits(ctx, z3_sort)
            sbits = z3.Z3_fpa_get_sbits(ctx, z3_sort)
            sort = FSort.from_params(ebits, sbits)

            return FPI(NativeFPV(value, sort))
        elif op_name in ('MinusZero', 'MinusInf', 'PlusZero', 'PlusInf', 'NaN'):
            ebits = z3.Z3_fpa_get_ebits(ctx, z3_sort)
            sbits = z3.Z3_fpa_get_sbits(ctx, z3_sort)
            sort = FSort.from_params(ebits, sbits)

            if op_name == 'MinusZero':
                return FPI(NativeFPV(-0.0, sort))
            elif op_name == 'MinusInf':
                return FPI(NativeFPV(float('-inf'), sort))
            elif op_name == 'PlusZero':
                return FPI(NativeFPV(0.0, sort))
            elif op_name == 'PlusInf':
                return FPI(NativeFPV(float('inf'), sort))
            elif op_name == 'NaN':
                return FPI(NativeFPV(float('nan'), sort))
        elif op_name == 'UNINTERPRETED': # this *might* be a BitVec ;-)
            bv_name = z3.Z3_get_symbol_string(ctx, z3.Z3_get_decl_name(ctx, decl))
            bv_size = z3.Z3_get_bv_sort_size(ctx, z3_sort)

            #if bv_name.count('_') < 2:
            #      import ipdb; ipdb.set_trace()
            return BV("BitVec", (bv_name, bv_size), length=bv_size, variables={ bv_name }, symbolic=True)
        elif op_name == 'Extract':
            hi = z3.Z3_get_decl_int_parameter(ctx, decl, 0)
            lo = z3.Z3_get_decl_int_parameter(ctx, decl, 1)
            args = [ hi, lo ]
        elif op_name in ('SignExt', 'ZeroExt'):
            num = z3.Z3_get_decl_int_parameter(ctx, decl, 0)
            args = [ num ]
        elif op_name in ('fpToFP', 'fpToFPSigned'):
            exp = z3.Z3_fpa_get_ebits(ctx, z3_sort)
            mantissa = z3.Z3_fpa_get_sbits(ctx, z3_sort)
            sort = FSort.from_params(exp, mantissa)
            args = children + [sort]
            append_children = False
        elif op_name in ('fpToSBV', 'fpToUBV'):
            # uuuuuugggggghhhhhh
            bv_size = z3.Z3_get_bv_sort_size(ctx, z3_sort)
            args = children + [bv_size]
            append_children = False
        else:
            args = [ ]

        if append_children:
            args.extend(children)

        # fix up many-arg __add__
        if op_name in bin_ops and len(args) > 2:
            many_args = args #pylint:disable=unused-variable
            last = args[-1]
            rest = args[:-1]

            a = args[0].make_like(op_name, rest[:2])
            for b in rest[2:]:
                a = args[0].make_like(op_name, [a,b])
            args = [ a, last ]

        # hmm.... honestly not sure what to do here
        result_ty = op_type_map[z3_op_nums[decl_num]]
        ty = type(args[-1])

        if op_name == 'If':
            # If is polymorphic and thus must be handled specially
            ty = type(args[1])

            a = ty('If', tuple(args), length=args[1].length)
        else:
            if hasattr(ty, op_name) or hasattr(_all_operations, op_name):
                op = getattr(ty if hasattr(ty, op_name) else _all_operations, op_name)
                if op.calc_length is not None:
                    length = op.calc_length(*args)
                    a = result_ty(op_name, tuple(args), length=length)
                else:
                    a = result_ty(op_name, tuple(args))
            else:
                a = result_ty(op_name, tuple(args))

        self._ast_cache[h] = a
        return a