Exemplo n.º 1
0
 def extract_eq(expr):
     kind = expr.decl().kind()
     children = expr.children()
     if kind == z3.Z3_OP_EQ:
         lhs = children[0]
         rhs = children[1]
         if z3.is_var(lhs):
             return z3.get_var_index(lhs), rhs
         elif z3.is_var(rhs):
             return z3.get_var_index(rhs), lhs
         else:
             return None
     return None
Exemplo n.º 2
0
    def translate(self, expr, bound_variables=[]):
        if z3.is_const(expr):
            return self.mk_const(expr)
#                raise Z3_Unexpected_Expression('Unrecognized constant')
        elif z3.is_var(expr):    # a de Bruijn indexed bound variable
            bv_length = len(bound_variables)
            return bound_variables[bv_length - z3.get_var_index(expr) - 1]
        elif z3.is_app(expr):
            args = [self.translate(expr.arg(i), bound_variables)
                for i in range(expr.num_args())]
            return self.mk_fun(expr.decl())(*args)

#            else:
#                raise Z3_Unexpected_Expression(expr)
        elif z3.is_quantifier(expr):
            num_vars = expr.num_vars()
#            vars = [language.const_dict[expr.var_name(i)]
#                for i in range(num_vars)]
            vars = [const(expr.var_name(i), self.mk_sort(expr.var_sort(i))) \
                for i in range(num_vars)]
            new_bound_variables = bound_variables + vars
            body = self.translate(expr.body(), new_bound_variables)
            if expr.is_forall():
                return forall(vars, body)
            else:
                return exists(vars, body)

        elif z3.is_func_decl(expr):
            return self.mk_fun(expr)
        else:
            print expr.kind
            raise Z3_Unexpected_Expression(expr)
Exemplo n.º 3
0
def extract_equal(eq):
    """Transform equals in a triple: var index, value, mask"""
    if isinstance(eq.children()[0], z3.BitVecNumRef):
        rhs = eq.children()[0]
        lhs = eq.children()[1]
    else:
        rhs = eq.children()[1]
        lhs = eq.children()[0]
    if z3.is_var(lhs):
        return ResultItem(
            var=z3.get_var_index(lhs),
            value=rhs,
            mask=None)
    else:
        kind = lhs.decl().kind()
        if kind == z3.Z3_OP_EXTRACT:
            [high, low] = lhs.params()
            sort = lhs.children()[0].sort()
            val = rhs.as_long() << low
            mask = (1 << (high + 1)) - (1 << low)
            return ResultItem(
                var=z3.get_var_index(lhs.children()[0]),
                value=z3.BitVecVal(val, sort),
                mask=z3.BitVecVal(mask, sort))
        else:
            raise base.Z3NotWellFormed(
                "Bad lhs for equal  {}".format(eq))
Exemplo n.º 4
0
def partial_leaf_substitution(expr, substitution_dict):
    """Replaces consts/vars in `expr` according to `substitution_dict`.

    If a const/var is not in `substitution_dict.keys()`, it remains
    unchanged.

    >>> a, b, c = sl.list.locs("a b c")
    >>> subst = {b : c}
    >>> partial_leaf_substitution(sl.sepcon(sl.list("a"), sl.list("b")), subst)
    sl.sepcon(sl.list(a), sl.list(c))
    >>> i, j = Ints("i j")
    >>> subst = {sl.alpha : i, sl.beta : j}
    >>> partial_leaf_substitution(sl.alpha < sl.beta, subst)
    i < j

    """
    if z3.is_const(expr) or z3.is_var(expr):
        return substitution_dict.get(expr, expr)
    elif z3.is_app(expr):
        new_args = [
            partial_leaf_substitution(child, substitution_dict)
            for child in expr.children()
        ]
        return replace_args(expr, new_args)
    else:
        assert (z3.is_quantifier(expr))
        new_arg = partial_leaf_substitution(expr.body(), substitution_dict)
        return replace_args(expr, new_arg)
Exemplo n.º 5
0
    def translate(self, expr, bound_variables=[]):
        if z3.is_const(expr):
            return self.mk_const(expr)
#                raise Z3_Unexpected_Expression('Unrecognized constant')
        elif z3.is_var(expr):    # a de Bruijn indexed bound variable
            bv_length = len(bound_variables)
            return bound_variables[bv_length - z3.get_var_index(expr) - 1]
        elif z3.is_app(expr):
            args = [self.translate(expr.arg(i), bound_variables)
                for i in range(expr.num_args())]
            return self.mk_fun(expr.decl())(*args)

#            else:
#                raise Z3_Unexpected_Expression(expr)
        elif z3.is_quantifier(expr):
            num_vars = expr.num_vars()
#            vars = [language.const_dict[expr.var_name(i)]
#                for i in range(num_vars)]
            vars = [const(expr.var_name(i), self.mk_sort(expr.var_sort(i))) \
                for i in range(num_vars)]
            new_bound_variables = bound_variables + vars
            body = self.translate(expr.body(), new_bound_variables)
            if expr.is_forall():
                return forall(vars, body)
            else:
                return exists(vars, body)

        elif z3.is_func_decl(expr):
            return self.mk_fun(expr)
        else:
            print expr.kind
            raise Z3_Unexpected_Expression(expr)
Exemplo n.º 6
0
 def convert(t, values):
     if z3.is_int_value(t):
         return t.as_long()
     if z3.is_app(t):
         func = globals()[t.decl().name()]
         return func(
             *[convert(t.arg(i), values) for i in range(t.num_args())])
     elif z3.is_var(t):
         return values[z3.get_var_index(t)]
Exemplo n.º 7
0
 def pp_expr(self, a, d, xs):
     self.visited = self.visited + 1
     if d > self.max_depth or self.visited > self.max_visited:
         return self.pp_ellipses()
     if z3.is_app(a):
         return self.pp_app(a, d, xs)
     elif z3.is_quantifier(a):
         return self.pp_quantifier(a, d, xs)
     elif z3.is_var(a):
         return self.pp_var(a, d, xs)
     else:
         return to_format(self.pp_unknown())
Exemplo n.º 8
0
 def pp_expr(self, a, d, xs):
     self.visited = self.visited + 1
     if d > self.max_depth or self.visited > self.max_visited:
         return self.pp_ellipses()
     if z3.is_app(a):
         return self.pp_app(a, d, xs)
     elif z3.is_quantifier(a):
         return self.pp_quantifier(a, d, xs)
     elif z3.is_var(a):
         return self.pp_var(a, d, xs)
     else:
         return to_format(self.pp_unknown())
Exemplo n.º 9
0
def tagged_conditional_rewrite(s, rewriting_dict, leaf_fn, default_fn):
    """
    Apply given rewriter to subexpressions of s bottom up
    """
    todo = []
    todo.append(s)
    cache = {}
    while todo:
        n = todo[len(todo) - 1]
        #print("Rewriting {}".format(n))
        #print("Current cache: {}".format(cache))
        if z3.is_var(n):
            # No rewriting for variables
            todo.pop()
            # TODO: This is one difference => Could be added as leaf_fn to standard rewrite as well
            cache[n] = leaf_fn(n)
        elif z3.is_app(n):
            # Add non-rewritten children to rewriting stack
            processed_all_children = True
            for arg in n.children():
                if arg not in cache:
                    todo.append(arg)
                    processed_all_children = False
            # All children haven been rewritten, so now rewrite n itself
            if processed_all_children:
                todo.pop()
                new_args = [cache[arg] for arg in n.children()]
                enabled_rewriter = rewriting_dict.get(n.decl())
                if enabled_rewriter is not None:
                    cache[n] = enabled_rewriter(n, new_args)
                else:
                    #cache[n] = replace_args(n, new_args)
                    cache[n] = default_fn(n, new_args)
        else:
            assert (z3.is_quantifier(n))
            b = n.body()
            if b in cache:
                # The argument of the quantifier has already been rewritten
                # Substitute this rewritten term
                todo.pop()
                # TODO: Another difference (but actually not even relevant in our setting). This could also be encapsulated in a function argument which could default to replace_args in the non-tagged setting
                rewritten_arg, tag = cache[b]
                cache[n] = (replace_args(n, [rewritten_arg]), tags)
            else:
                todo.append(b)
    return cache[s]
Exemplo n.º 10
0
def conditional_rewrite(s, rewriting_dict, default_fn=replace_args):
    """
    Apply given rewriter to subexpressions of s bottom up
    """
    todo = []
    todo.append(s)
    cache = {}
    while todo:
        n = todo[len(todo) - 1]
        #print(n)
        if z3.is_var(n):
            # No rewriting for variables
            todo.pop()
            cache[n] = default_leaf_fn(n)
        elif z3.is_app(n):
            # Add non-rewritten children to rewriting stack
            processed_all_children = True
            for arg in n.children():
                if arg not in cache:
                    todo.append(arg)
                    processed_all_children = False
            # All children haven been rewritten, so now rewrite n itself
            if processed_all_children:
                todo.pop()
                new_args = [cache[arg] for arg in n.children()]
                enabled_rewriter = rewriting_dict.get(n.decl())
                if enabled_rewriter is not None:
                    #print("Match for {}".format(n.decl()))
                    cache[n] = enabled_rewriter(n, new_args)
                else:
                    #cache[n] = replace_args(n, new_args)
                    cache[n] = default_fn(n, new_args)
        else:
            assert (z3.is_quantifier(n))
            b = n.body()
            if b in cache:
                # The argument of the quantifier has already been rewritten
                # Substitute this rewritten term
                todo.pop()
                cache[n] = replace_args(n, [cache[b]])
            else:
                todo.append(b)
    return cache[s]
Exemplo n.º 11
0
def rec_go(formula, var_list, reduction_type, q_type, bit_places, polarity):
    """Recursively go through the formula and apply approximations.
    """
    # Constant
    if z3.is_const(formula):
        pass

    # Variable
    elif z3.is_var(formula):
        order = - z3.get_var_index(formula) - 1

        # Process if it is bit-vector variable
        if type(formula) == z3.BitVecRef:
            # Update max bit-vector width
            global max_bit_width
            if max_bit_width < formula.size():
                max_bit_width = formula.size()

            # Approximate if var is quantified in the right way
            if var_list[order][1] == q_type:
                formula = approximate(formula, reduction_type, bit_places)

    # Quantified formula
    elif type(formula) == z3.QuantifierRef:
        formula = qform_process(formula,
                                list(var_list),
                                reduction_type,
                                q_type,
                                bit_places,
                                polarity)

    # Complex formula
    else:
        formula = cform_process(formula,
                                list(var_list),
                                reduction_type,
                                q_type,
                                bit_places,
                                polarity)

    return formula
Exemplo n.º 12
0
def unique_leaves(exp, leaf_keys=None):
    def insert_and_yield(e):
        k = exp_key(e)
        if k not in leaf_keys:
            leaf_keys.append(k)
            yield e

    if leaf_keys is None: leaf_keys = []

    if z3.is_const(exp) and not (z3.is_int_value(exp)
                                 or z3.is_rational_value(exp)):
        for leaf in insert_and_yield(exp):
            yield leaf
    elif z3.is_app(exp):
        for i in range(exp.num_args()):
            for leaf in unique_leaves(exp.arg(i), leaf_keys):
                yield leaf
    else:
        assert z3.is_var(exp)
        for leaf in insert_and_yield(exp):
            yield leaf
Exemplo n.º 13
0
def check_chc_head(expr):
    if u_predicate(expr):
        decl = expr.decl()
        if decl is not None:
            known_vars = Set([])
            for kid in expr.children():
                if not z3.is_var(kid):
                    raise Exception("illegal head: " +
                                    "argument {} is not a variable {}".format(
                                        expr.sexpr(), kid.sexpr()))
                index = z3.get_var_index(kid)
                if index in known_vars:
                    raise Exception("illegal head: non-distinct arguments, " +
                                    "{} is used twice in {}".format(
                                        kid.sexpr(), expr.sexpr()))
                known_vars.add(z3.get_var_index(kid))
        return False
    elif expr == z3.BoolVal(False):
        return True
    else:
        raise Exception("illegal head: {}".format(expr.sexpr()))
Exemplo n.º 14
0
def tree_conditional_rewrite(expr, rewriting_dict, default_fn=replace_args):
    """Rewrite `expr` bottom up, deliberately ignoring sharing in the DAG.

    """
    if z3.is_var(expr):
        return default_leaf_fn(expr)
    elif z3.is_app(expr):
        new_args = [
            tree_conditional_rewrite(child, rewriting_dict, default_fn)
            for child in expr.children()
        ]
        enabled_rewriter = rewriting_dict.get(expr.decl())
        if enabled_rewriter is not None:
            #print("Match for {}".format(n.decl()))
            return enabled_rewriter(expr, new_args)
        else:
            return default_fn(expr, new_args)
    else:
        assert (z3.is_quantifier(expr))
        new_arg = tree_conditional_rewrite(expr.body(), rewriting_dict,
                                           default_fn)
        return replace_args(expr, new_arg)
Exemplo n.º 15
0
def u_predicate(expr, distinct_vars):
    """Returns True if expr is a valid u_predicate, False if it's not a
    predicate application, and raises an exception if it's an invalid predicate
    application.

    Argument `distinct_vars` forces to check that all arguments are
    distinct."""
    if is_pred_app(expr):
        vars = set([])
        for index, kid in enumerate(expr.children()):
            if not z3.is_var(kid):
                raise Exc('Argument {} of application of {} '
                          'is not a variable: {}'.format(
                              index,
                              expr.decl().name(), kid.sexpr()))
            if distinct_vars and kid in vars:
                raise Exc(
                    'Illegal predicate application in head: all arguments '
                    'need to be distinct variables')
            vars.add(kid)
        return True
    else:
        return False
Exemplo n.º 16
0
    def smtify(expr, children):
        if z3.is_var(expr):
            # TODO: Allow more than one quantified var?
            assert str(expr)=='Var(0)', \
                'Currently only support for expressions with a single quantified variable'
            return '_x_'
        elif z3.is_quantifier(expr):
            assert expr.num_vars() == 1, \
                'Currently only support for expressions with a single quantified variable'

            return '{}({} ((_x_ {}))\n{})'.format(
                'forall' if expr.is_forall() else 'exists',
                expr.var_sort(0),
                children[0]
            )
        else:
            #print('{!r} with children {!r}'.format(expr, children))
            assert z3.is_app(expr)
            assert isinstance(encoding, z3.ExprRef)
            # TODO: Improve/simplify the whitespace handling
            sjoin = '\n' if multi_line else ' '
            child_string = sjoin.join(children)
            if indent:
                child_string = textwrap.indent(child_string, indent)
            stripped = pat.sub(' ', child_string)
            while stripped[0] == ' ':
                stripped = stripped[1:]
            if len(stripped) < 20 or not multi_line:
                rep = stripped
            else:
                rep = '\n' + child_string

            res = '({} {})'.format(
                translate_head_func_decl(expr),
                rep)
            #print('Will return {}'.format(res))
            return res
Exemplo n.º 17
0
def check_chc_tail(expr):
    """Checks that predicate declarations are first, and that there's only one
    i_formula after them."""
    if z3.is_const(expr) \
    or z3.is_var(expr) \
    or expr.decl().kind() != z3.Z3_OP_AND:
        raise Exc('Illegal tail: expected conjunction, got {}'.format(
            expr.sexpr()))
    else:
        i_formula_count = 0
        for kid in expr.children():
            if u_predicate(kid, False):
                if i_formula_count > 1:
                    raise Exc(
                        "Illegal tail: "
                        "predicate application(s) appears after i_formula")
            elif i_formula(kid):
                i_formula_count += 1
            else:
                raise Exc("Illegal conjunct in tail: {}".format(kid.sexpr()))
        if i_formula_count > 1:
            raise Exc(("Illegal tail: expected 0 or 1 i_formula, "
                       "got {}").format(i_formula_count))
    return True
Exemplo n.º 18
0
def unique_var_leaves(exp):
    for l in unique_leaves(exp):
        if z3.is_var(l): yield l
Exemplo n.º 19
0
 def add(expr):
     if z3.is_var(expr):
         vars.append(expr)
Exemplo n.º 20
0
 def var_name(self, rule, i):
     """ yields the name of a variable """
     if z3.is_var(i):
         i = z3.get_var_index()
     # (variables are numbered backwards within the predicates)
     return rule.var_name(rule.num_vars() - 1 - i)
Exemplo n.º 21
0
def bound_var_sort (quant, var):
  if z3.is_var (var):
    var = z3.get_var_index ()
  return quant.var_sort (quant.num_vars () - 1 - var)
Exemplo n.º 22
0
 def var_name(self,rule,i):
     """ yields the name of a variable """
     if z3.is_var(i): i = z3.get_var_index()
     # (variables are numbered backwards within the predicates)
     return rule.var_name(rule.num_vars()-1-i)
Exemplo n.º 23
0
def unique_const_leaves(exp):
    for l in unique_leaves(exp):
        if not z3.is_var(l): yield l
Exemplo n.º 24
0
def bound_var_sort (quant, var):
  if z3.is_var (var):
    var = z3.get_var_index ()
  return quant.var_sort (quant.num_vars () - 1 - var)
Exemplo n.º 25
0
def is_pred_app(expr):
    return (not z3.is_var(expr) and z3.is_expr(expr)
            and expr.decl().kind() == z3.Z3_OP_UNINTERPRETED)
Exemplo n.º 26
0
 def i_formula_node(expr):
     if not z3.is_var(expr) and not z3.is_const(expr):
         decl = expr.decl()
         if decl.kind() == z3.Z3_OP_UNINTERPRETED:
             list.append(False)
Exemplo n.º 27
0
    def substitute(self, other, expr):
        def update_term(t, args):
            n = len(args)
            # Need to pass an AstArray type into Z3_update_term, not a python list
            args_ast_arr = (z3.Ast * n)()
            for i in range(n):
                args_ast_arr[i] = args[i].as_ast()
            return _to_expr_ref(
                z3.Z3_update_term(t.ctx_ref(), t.as_ast(), n, args_ast_arr),
                t.ctx)

        cache = z3.AstMap(ctx=expr.ctx)

        for addr, state in self._expanded_global_state.items():
            other_state = other.initial_contract_state(addr)
            cache[state.storage] = other_state.storage
            cache[state.balance] = other_state.balance
            cache[state.nonce] = other_state.nonce

        fnsubs = []
        for k, v in self._cache.items():
            if isinstance(v, mem.Memory):
                # Uses of Memory objects will produce an expression containing
                # the underlying array object (_mem). If required the index
                # (_idx) will have been substituted with the actual indexing
                # expression at that point, so we do not need to consider it
                # here.
                cache[v._mem] = getattr(other, k)()._mem
            elif z3.is_app(v) and v.num_args() > 0:
                fnsubs.append((v, getattr(other, k)()))
            else:
                cache[v] = getattr(other, k)()

        todo = [expr]
        while todo:
            n = todo[-1]
            if n in cache:
                todo.pop()
            elif z3.is_var(n):
                cache[n] = n
                todo.pop()
            elif z3.is_app(n):
                new_args = []
                for i in range(n.num_args()):
                    arg = n.arg(i)
                    if arg not in cache:
                        todo.append(arg)
                    else:
                        new_args.append(cache[arg])
                # Only actually do the substitution if all the arguments have
                # already been processed
                if len(new_args) == n.num_args():
                    todo.pop()
                    fn = n.decl()
                    for oldfn, newfn in fnsubs:
                        if z3.eq(fn, oldfn):
                            new_fn = z3.substitute_vars(newfn, *new_args)
                            break
                    else:
                        # TODO only if new_args != old_args
                        if len(new_args) != fn.arity():
                            new_fn = update_term(n, new_args)
                        else:
                            new_fn = fn(*new_args)
                    cache[n] = new_fn
            else:
                assert z3.is_quantifier(n)
                # Not currently implemented as don't use quanitifers at the
                # moment
                raise NotImplementedError()
        return cache[expr]