Esempio n. 1
0
def model_value_to_python(value: z3.ExprRef) -> object:
    if z3.is_string_value(value):
        return value.as_string()
    elif z3.is_real(value):
        return float(value.as_fraction())
    else:
        return ast.literal_eval(repr(value))
Esempio n. 2
0
 def __k_bool__(self):
     if z3.is_int(self.value) or z3.is_real(self.value) or z3.is_bv(
             self.value):
         yield inference.InferenceResult(Z3Proxy.init_expr(
             self.value != 0, self.defaults),
                                         status=True)
     elif z3.is_string(self.value):
         yield inference.InferenceResult(Z3Proxy.init_expr(
             self.value != z3.StringVal(""), self.defaults),
                                         status=True)
     else:
         yield inference.InferenceResult(self, status=True)
Esempio n. 3
0
def get_py_val_from_z3_val(z3_result):
    if z3_result is not None:
        if z3.is_int_value(z3_result):
            return z3_result.as_long()
        elif z3.is_real(z3_result):
            return float(z3_result.numerator_as_long()) / float(
                z3_result.denominator_as_long())
        elif z3.is_true(z3_result):
            return True
        elif z3.is_false(z3_result):
            return False
        elif z3.is_string_value(z3_result):
            return z3_result.as_string()
        else:
            raise NotImplementedError(
                "Z3 model result other than int, real, bool, string is not supported yet!"
            )
Esempio n. 4
0
 def _enc_real_expr(self, c):
     if z3.is_real(c):
         return c
     elif isinstance(c, float):
         return c
     elif isinstance(c, int):
         return float(c)
     elif isinstance(c, VerifierVar):
         return c.get()
     elif isinstance(c, SumExpr):
         s = self._enc_real_expr(c.parts[0])
         for p in c.parts[1:]:
             s += self._enc_real_expr(p)
         return s
     else:
         raise RuntimeError("unsupported VerifierRealExpr of type " +
                            type(c).__qualname__)
Esempio n. 5
0
def _gen(expr_z3, symbolTable, cache, result):

    ###Leaf: var
    if _is_variable(expr_z3):
        if DEBUG: print "-- Branch _is_variable with ", expr_z3
        symVar = expr_z3.decl().name()

        symVar = rename_var(symVar)

        if z3.is_int(expr_z3): symType = Sort.Int
        elif z3.is_fp(expr_z3):
            if expr_z3.sort() == z3.Float64():
                symType = Sort.Float64
            elif expr_z3.sort() == z3.Float32():
                symType = Sort.Float32
            else:
                raise NotImplementedError("Unexpected sort.", expr_z3.sort())
        elif z3.is_real(expr_z3):
            symType = Sort.Float
            warnings.warn(
                "****WARNING****: Real variable '%s' treated as floating point"
                % symVar)
        else:
            raise NotImplementedError("Unexpected type for %s" % symbolName)
        if (symVar in symbolTable.keys()):
            assert symType == symbolTable[symVar]
        else:
            symbolTable[symVar] = symType

        if expr_z3.sort() == z3.Float32():
            symVar = "TR32(%s)" % symVar  # do the same ting for verify !!!!!!!!

        return symVar

    ###Leaf: val
    if _is_value(expr_z3):
        if DEBUG: print "-- Branch _is_value"
        if z3.is_fp(expr_z3) or z3.is_real(expr_z3):
            if DEBUG: print "---- Sub-Branch FP or Real"
            if isinstance(expr_z3, z3.FPNumRef):
                if DEBUG: print "------- Sub-Sub-Branch _is_FPNumRef"
                try:
                    str_ret = str(sympy.Float(str(expr_z3), 17))

                except ValueError:
                    if expr_z3.isInf() and expr_z3.decl().kind(
                    ) == z3.Z3_OP_FPA_PLUS_INF:
                        str_ret = "INFINITY"
                    elif expr_z3.isInf() and expr_z3.decl().kind(
                    ) == z3.Z3_OP_FPA_MINUS_INF:
                        str_ret = "- INFINITY"
                    elif expr_z3.isNaN():
                        str_ret = "NAN"
                    else:
                        offset = 127 if expr_z3.sort() == z3.Float32(
                        ) else 1023
                        #Z3 new version needs the offset to be taken into consideration
                        expr_z3_exponent = expr_z3.exponent_as_long() - offset

                        str_ret = str(
                            sympy.Float((-1)**float(expr_z3.sign()) *
                                        float(str(expr_z3.significand())) *
                                        2**(expr_z3_exponent), 17))

            else:
                if DEBUG:
                    print "------- Sub-Sub-Branch other than FPNumRef, probably FPRef"
                str_ret = str(sympy.Float(str((expr_z3)), 17))
        elif z3.is_int(expr_z3):
            if DEBUG: print "---- Sub-Branch Integer"
            str_ret = str(sympy.Integer(str(expr_z3)))
        elif _is_true(expr_z3):

            str_ret = "0"
        elif _is_false(expr_z3):
            str_ret = "1"
        else:
            raise NotImplementedError(
                "[XSat: Coral Benchmarking] type not considered ")

        if expr_z3.sort() == z3.Float32():
            str_ret = str_ret + "f"

        return str_ret

    #if (expr_z3 in cache): return cache[expr_z3]

    #cache will be a set of defined IDs
    #if (var_name(expr_z3) in cache): return cache[expr_z3]

    if (expr_z3.get_id() in cache): return var_name(expr_z3)

    cache.add(expr_z3.get_id())
    #cache[expr_z3]=var_name(expr_z3)

    sort_z3 = expr_z3.decl().kind()

    expr_type = 'double'
    if expr_z3.sort() == z3.FPSort(8, 24): expr_type = 'float'

    ###
    if sort_z3 == z3.Z3_OP_FPA_LE:
        if DEBUG: print "-- Branch _is_le"
        lhs = _gen(expr_z3.arg(0), symbolTable, cache, result)
        rhs = _gen(expr_z3.arg(1), symbolTable, cache, result)
        toAppend= "double %s = DLE(%s,%s); " \
                  %( var_name(expr_z3), \
                     lhs,\
                     rhs,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    #########!!!!!!!!!!!! need to do something
    if sort_z3 == z3.Z3_OP_FPA_TO_FP:
        if DEBUG: print "-- Branch _is_fpFP"
        assert expr_z3.num_args() == 2
        if not (_is_RNE(expr_z3.arg(0))):
            warnings.warn(
                "WARNING!!! I expect the first argument of fpFP is RNE, but it is ",
                expr_z3.arg(0))

        x = _gen(expr_z3.arg(1), symbolTable, cache, result)
        if expr_z3.sort() == z3.FPSort(8, 24):
            x = "TR32(%s)" % x
        #else if expr_z3.sort()==z3.FPSort(8,24):
        #    x = "TR(%s)"  %x

        toAppend= "%s %s = %s; " \
                  %( expr_type, var_name(expr_z3), \
                     x,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if sort_z3 == z3.Z3_OP_FPA_LT:
        if DEBUG: print "-- Branch _is_lt"
        lhs = _gen(expr_z3.arg(0), symbolTable, cache, result)
        rhs = _gen(expr_z3.arg(1), symbolTable, cache, result)
        toAppend= "double %s = DLT(%s,%s);" \
                  %( var_name(expr_z3), \
                     lhs,\
                     rhs,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if _is_eq(expr_z3):
        if DEBUG: print "-- Branch _is_eq"
        lhs = _gen(expr_z3.arg(0), symbolTable, cache, result)
        rhs = _gen(expr_z3.arg(1), symbolTable, cache, result)
        toAppend= "double %s = DEQ(%s,%s);" \
                  %( var_name(expr_z3), \
                        lhs,\
                     rhs,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if _is_fpMul(expr_z3):
        if DEBUG: print "-- Branch _is_fpMul"
        if not _is_RNE(expr_z3.arg(0)):
            warnings.warn(
                "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ",
                expr_z3.arg(0))
        assert expr_z3.num_args() == 3
        lhs = _gen(expr_z3.arg(1), symbolTable, cache, result)
        rhs = _gen(expr_z3.arg(2), symbolTable, cache, result)
        toAppend= "%s %s = %s*%s; " \
                  %( expr_type, var_name(expr_z3), \
                        lhs,\
                     rhs,\

                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if _is_fpDiv(expr_z3):
        if DEBUG: print "-- Branch _is_fpDiv"
        if not _is_RNE(expr_z3.arg(0)):
            warnings.warn(
                "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ",
                expr_z3.arg(0))
        assert expr_z3.num_args() == 3
        lhs = _gen(expr_z3.arg(1), symbolTable, cache, result)
        rhs = _gen(expr_z3.arg(2), symbolTable, cache, result)
        toAppend= "%s %s = %s/%s; " \
                  %(expr_type,  var_name(expr_z3), \
                        lhs,\
                     rhs,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if _is_fpAdd(expr_z3):
        if DEBUG: print "-- Branch _is_fpAdd"
        if not _is_RNE(expr_z3.arg(0)):
            warnings.warn(
                "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ",
                expr_z3.arg(0))
        assert expr_z3.num_args() == 3
        lhs = _gen(expr_z3.arg(1), symbolTable, cache, result)
        rhs = _gen(expr_z3.arg(2), symbolTable, cache, result)
        toAppend= "%s %s = %s+%s;" \
                  %( expr_type, var_name(expr_z3), \
                        lhs,\
                     rhs,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if z3.is_and(expr_z3):
        if DEBUG: print "-- Branch _is_and"
        ##TODO Not sure if symbolTable will be treated in a multi-threaded way
        toAppendExpr = _gen(expr_z3.arg(0), symbolTable, cache, result)
        for i in range(1, expr_z3.num_args()):
            toAppendExpr = 'BAND( %s,%s )' % (
                toAppendExpr, _gen(expr_z3.arg(i), symbolTable, cache, result))

        toAppend= "double %s = %s; " \
                  %( var_name(expr_z3), \
                     toAppendExpr,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if z3.is_not(expr_z3):
        if DEBUG: print "-- Branch _is_not"
        assert expr_z3.num_args() == 1
        if not (expr_z3.arg(0).num_args() == 2):
            warnings.warn(
                "WARNING!!! arg(0) is not RNE but is treated as RNE. arg(0) = ",
                expr_z3.arg(0))
        op1 = _gen(expr_z3.arg(0).arg(0), symbolTable, cache, result)
        op2 = _gen(expr_z3.arg(0).arg(1), symbolTable, cache, result)
        if _is_ge(expr_z3.arg(0)):
            a = "DLT(%s,%s)" % (op1, op2)
        elif _is_gt(expr_z3.arg(0)):
            a = "DLE(%s,%s)" % (op1, op2)
        elif _is_le(expr_z3.arg(0)):
            a = "DGT(%s,%s)" % (op1, op2)
        elif _is_lt(expr_z3.arg(0)):
            a = "DGE(%s,%s)" % (op1, op2)
        elif _is_eq(expr_z3.arg(0)):
            a = "DNE(%s,%s)" % (op1, op2)
        elif _is_distinct(expr_z3.arg(0)):
            a = "DEQ(%s,%s)" % (op1, op2)
        else:
            raise NotImplementedError(
                "Not implemented case 004 for expr_z3  =  %s. 'Not(or... )' is not handled yet"
                % expr_z3)
        toAppend= "%s %s = %s; " \
                  %( expr_type, var_name(expr_z3), \
                     a,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    if _is_fpNeg(expr_z3):
        if DEBUG: print "-- Branch _is_fpNeg"
        assert expr_z3.num_args() == 1
        op1 = _gen(expr_z3.arg(0), symbolTable, cache, result)
        toAppend = "%s %s =  - %s ;" \
                  %(expr_type, var_name(expr_z3), \
                     op1,\
                  )
        result.append(toAppend)
        return var_name(expr_z3)

    raise NotImplementedError(
        "Not implemented case 002 for expr_z3  =  %s, kind(%s)" %
        (expr_z3, expr_z3.decl().kind()))
Esempio n. 6
0
def walk_block(node, prev_g=None, cond=True):
    g = z3.Goal()
    g.add(cond)
    if prev_g is not None:
        for e in prev_g:
            if isinstance(e, z3.Goal):
                g.add(e.as_expr())
            else:
                g.add(e)

    if isinstance(node, pycp.c_ast.Compound):
        if node.block_items is not None:
            for e in node.block_items:
                g_next = walk_block(e, g)
                g = g_next
    elif isinstance(node, pycp.c_ast.Decl):
        if "int" in node.type.type.names:
            vars[node.name] = z3.Int(node.name)
        if "float" in node.type.type.names:
            vars[node.name] = z3.Real(node.name)
    elif isinstance(node, pycp.c_ast.FuncCall):
        if node.name.name == "__ASSUME":
            for e_exp in node.args.exprs:
                g.add(gen_smt_expr(e_exp))
        elif node.name.name == "__ASSERT":
            assertions = z3.Goal()
            for e_exp in node.args.exprs:
                assertions.add(gen_smt_expr(e_exp))
            print("solving..")
            print("SP:", g.as_expr())
            print("assert:", assertions)

            seen = set()

            def bv_length(e):
                li = [-1]
                if e in seen:
                    return -1
                if (z3.is_bv(e) and
                        z3.is_const(e) and
                        e.decl().kind() == z3.Z3_OP_UNINTERPRETED):
                    li.append(e.size())
                seen.add(e)
                if z3.is_app(e):
                    for ch in e.children():
                        li.append(bv_length(ch))
                elif z3.is_quantifier(e):
                    for ch in e.body().children():
                        li.append(bv_length(ch))
                return max(li)

            t = z3.Tactic('nla2bv')
            s = z3.Then(t, 'default').solver()
            fml = z3.And(g.as_expr(), z3.Not(assertions.as_expr()))
            print("solving using bitvector underapproximation..")
            s.add(fml)
            status = s.check()

            if status == z3.unknown:
                print("returned 'unknown'! trying again with bigger bit length..")
                print("getting highest bit length used in formula..")
                bv_l = bv_length(t(fml).as_expr())
                print("highest bit length used:", bv_l)

                while True:
                    bv_l += 1
                    print("trying with bit length:", bv_l)
                    s = z3.Then(z3.With('nla2bv', nla2bv_bv_size=bv_l),
                                'default').solver()
                    s.add(fml)
                    status = s.check()

                    if status != z3.unknown or bv_l >= 64:
                        break

            if status == z3.sat:
                model = s.model()
                print("program is unsafe.\nlisting an unsafe assignments..")
                for e in vars:
                    print(e, ':', model[vars[e]])
            elif status == z3.unsat:
                print("program is safe.")
            elif status == z3.unknown:
                print("unknown")

            s.reset()
        else:
            print("found a func call")
    elif isinstance(node, pycp.c_ast.Assignment):
        rexp = gen_smt_expr(node.rvalue)
        if z3.is_int(vars[node.lvalue.name]):
            hand_ = z3.Int('__hand__')
        elif z3.is_real(vars[node.lvalue.name]):
            hand_ = z3.Real('__hand__')
        if node.op == "=":
            g.add(hand_ == rexp)
        elif node.op == "+=":
            g.add(hand_ == (vars[node.lvalue.name] + rexp))
        elif node.op == "-=":
            g.add(hand_ == (vars[node.lvalue.name] - rexp))
        elif node.op == "*=":
            g.add(hand_ == (vars[node.lvalue.name] * rexp))
        elif node.op == "%=":
            g.add(hand_ == (vars[node.lvalue.name] % rexp))
        g_ = z3.Goal()
        g_.add(z3.Exists(vars[node.lvalue.name], g.as_expr()))
        g_ = t_qe_(g_)
        g = z3.Goal()
        g.add(z3.substitute(g_.as_expr(), (hand_, vars[node.lvalue.name])))
        # g = g.simplify()
    elif isinstance(node, pycp.c_ast.If):
        cond_exp = gen_smt_expr(node.cond)
        if node.iftrue is not None:
            true_expr = walk_block(node.iftrue, g, cond_exp).as_expr()
        else:
            true_expr = z3.And(cond_exp, g.as_expr())
        if node.iffalse is not None:
            false_expr = walk_block(
                node.iffalse, g, z3.Not(cond_exp)).as_expr()
        else:
            false_expr = z3.And(z3.Not(cond_exp), g.as_expr())
        g = z3.Goal()
        g.add(z3.Or(true_expr, false_expr))
        g = t(g)  # g.simplify()
    else:
        return prev_g
    # print(g.as_expr(), "\n")
    return g
    def _parseSmt1String(self, string):
        #self._logger.setVerbose(True)
        stack = list()
        functionSymbols = '&|~<=*+-'
        try:
            string = string.replace('\n', '').split('(')
            idx = 0
            for pos, elem in enumerate(string):
                self._logger.writeToLog('{} - reading :{}:'.format(pos, elem))
                if elem == '':
                    continue

                elemL = elem.split()
                # ALL lines should start with '('
                if elemL[0] in functionSymbols:
                    stack.append(elemL[0])
                elif elemL[0] == 'var':
                    varName = elemL[2].replace(')', '')
                    if elemL[1] == 'bool':
                        formula = z3.Bool(varName)
                        stack.append(self._abstraction(formula))
                    elif elemL[1] == 'real':
                        formula = z3.Real(varName)
                        stack.append(formula)
                    elif elemL[1] == 'int':
                        formula = z3.Int(varName)
                        stack.append(formula)
                    else:
                        raise Exception(
                            'Unknown Variable format: {}'.format(elemL))
                elif elemL[0] == 'const':
                    const = elemL[2].replace(')', '')
                    if elemL[1] == 'real':
                        stack.append(z3.RealVal(const))
                    elif elemL[1] == 'int':
                        stack.append(z3.IntVal(const))
                    else:
                        raise Exception(
                            'Unknown Constant format: {}'.format(elemL))
                else:
                    raise Exception('Unknown format : {}'.format(elemL))

                closedBrackets = elem.count(')') - 1
                self._logger.writeToLog(
                    "{} - new element in stack: {}\t,cB {}".format(
                        pos, stack[-1], closedBrackets))

                if closedBrackets < 1:
                    continue

                while closedBrackets > 0:
                    self._logger.writeToLog('{} - stack: {},{}'.format(
                        pos, stack, closedBrackets))
                    tmpPredi = []
                    pred = None
                    while True:
                        pred = stack.pop()
                        #if isinstance(pred,Predicate) or isinstance(pred,z3.BoolRef) or str(pred).replace('.','',1).isdigit():
                        #if z3.is_rational_value(pred) or z3.is_int_value(pred) or z3.is_int(pred) or z3.is_real(pred) or z3.is_bool(pred):
                        if isinstance(pred, float) or isinstance(
                                pred, int) or z3.is_int(pred) or z3.is_real(
                                    pred) or z3.is_bool(pred):
                            tmpPredi.append(pred)
                        else:
                            if len(tmpPredi) == 1:
                                tmpPredi = tmpPredi[0]
                            else:
                                tmpPredi = tmpPredi[::-1]
                            break
                    self._logger.writeToLog('{} - {} is applied to {}'.format(
                        pos, pred, tmpPredi))
                    newElem = self._mapFunctionSymbol(pred)(tmpPredi)
                    # newElemSimplified = z3.simplify(newElem)
                    stack.append(newElem)
                    self._logger.writeToLog(
                        "{} - new element in stack: {}\t,cB {}".format(
                            pos, stack[-1], closedBrackets))
                    closedBrackets -= 1
                self._logger.writeToLog('{} - finished :{}:'.format(
                    pos, stack))
        except Exception as e:
            self._logger.writeToLog(
                "Some Error : {}\n\t Occured parsing formula: {}".format(
                    e, string))
            raise e

        if len(stack) != 1:
            raise Exception("Parsing Error, stack != 1")
        return self._recusiveSimplification(stack[0])
Esempio n. 8
0
def _handleNum(state,left,right,op):
    # Match our object types
    leftZ3Object,rightZ3Object = z3Helpers.z3_matchLeftAndRight(left,right,op)

    # Figure out what the op is and add constraint
    if type(op) == ast.Add:
        if type(left) is BitVec:
            # Check for over and underflows
            state.solver.add(z3Helpers.bvadd_safe(leftZ3Object,rightZ3Object))

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() + right.getValue()

        else:
            ret = leftZ3Object + rightZ3Object

    elif type(op) == ast.Sub:
        if type(left) is BitVec:
            state.solver.add(z3Helpers.bvsub_safe(leftZ3Object,rightZ3Object))

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() - right.getValue()

        else:
            ret = leftZ3Object - rightZ3Object

    elif type(op) == ast.Mult:
        if type(left) is BitVec:
            state.solver.add(z3Helpers.bvmul_safe(leftZ3Object,rightZ3Object))

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() * right.getValue()

        else:
            ret = leftZ3Object * rightZ3Object

    elif type(op) == ast.Div:
        if type(left) is BitVec:
            state.solver.add(z3Helpers.bvdiv_safe(leftZ3Object,rightZ3Object))

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() / right.getValue()

        else:
            ret = leftZ3Object / rightZ3Object

    elif type(op) == ast.Mod:
        # Z3 doesn't have native support for Real type modular arithmetic
        if z3.is_real(leftZ3Object):
            constraint = []
            if z3.is_real(rightZ3Object):
                mod = z3.Function('mod', z3.RealSort(),z3.RealSort(), z3.RealSort())
                quot = z3.Function('quot', z3.RealSort(),z3.RealSort(), z3.RealSort())
                constraint += [z3Helpers.isInt(rightZ3Object)]
            else:
                mod = z3.Function('mod', z3.RealSort(),z3.IntSort(), z3.RealSort())
                quot = z3.Function('quot', z3.RealSort(),z3.IntSort(), z3.RealSort())
            constraint.append(0 <= mod(leftZ3Object,rightZ3Object))
            constraint.append(mod(leftZ3Object,rightZ3Object) < rightZ3Object)
            constraint.append(rightZ3Object * quot(leftZ3Object,rightZ3Object) + mod(leftZ3Object,rightZ3Object) == leftZ3Object)
            constraint.append(z3Helpers.isInt(quot(leftZ3Object,rightZ3Object)))
            constraint.append(z3Helpers.isInt(leftZ3Object))
            constraint.append(leftZ3Object >= 0)
            state.addConstraint(z3.And(constraint))
            """
            state.addConstraint(0 <= mod(leftZ3Object,rightZ3Object))
            state.addConstraint(mod(leftZ3Object,rightZ3Object) < rightZ3Object)
            state.addConstraint(rightZ3Object * quot(leftZ3Object,rightZ3Object) + mod(leftZ3Object,rightZ3Object) == leftZ3Object)
            state.addConstraint(z3Helpers.isInt(quot(leftZ3Object,rightZ3Object)))
            state.addConstraint(z3Helpers.isInt(leftZ3Object))
            state.addConstraint(leftZ3Object >= 0)
            """
            ret = mod(leftZ3Object,rightZ3Object)

        else:

            # Keep this out of the Z3 solver!
            if left.isStatic() and right.isStatic():
                ret = left.getValue() % right.getValue()

            else:
                ret = leftZ3Object % rightZ3Object

    elif type(op) == ast.BitXor:

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() ^ right.getValue()

        else:
            ret = leftZ3Object ^ rightZ3Object

    elif type(op) == ast.BitOr:

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() | right.getValue()

        else:
            ret = leftZ3Object | rightZ3Object

    elif type(op) == ast.BitAnd:
        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() & right.getValue()

        else:
            ret = leftZ3Object & rightZ3Object

    elif type(op) == ast.LShift:
        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() << right.getValue()

        else:
            ret = leftZ3Object << rightZ3Object

    elif type(op) == ast.RShift:

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() >> right.getValue()

        else:
            ret = leftZ3Object >> rightZ3Object

    # TODO: This one will fail if we use BitVecs.. Maybe think about check/convert?
    elif type(op) == ast.Pow:

        # Keep this out of the Z3 solver!
        if left.isStatic() and right.isStatic():
            ret = left.getValue() ** right.getValue()

        # Z3 has some problems with forms of x ** 0.5, let's try to change it for Z3...
        elif type(rightZ3Object) is z3.RatNumRef and rightZ3Object.numerator().as_long() == 1 and rightZ3Object.denominator().as_long() > 1:
            tmp = state.getVar("tempRootVar",ctx=1,varType=Real)
            tmp.increment()
            # Rewrite as x ** 2 == y form
            state.addConstraint(tmp.getZ3Object() ** float(rightZ3Object.denominator().as_long()) == leftZ3Object)
            # Because we're dealing with square, let's make sure it's positive
            state.addConstraint(tmp.getZ3Object() >= 0)
            ret = tmp.getZ3Object()

        else:
            ret = leftZ3Object ** rightZ3Object
            #ret = leftZ3Object ** rightZ3Object

    else:
        err = "BinOP: Don't know how to handle op type {0} at line {1} col {2}".format(type(op),op.lineno,op.col_offset)
        logger.error(err)
        raise Exception(err)

    # TODO: Clean up code below...
    # Duplicate the object and create a pyObjectManager object
    left_t,left_args = pyState.duplicateSort(leftZ3Object)
    right_t,right_args = pyState.duplicateSort(rightZ3Object)
    if left_t in [Int,Real,BitVec] and right_t in [Int, Real, BitVec]:
        # Not handling this case well right now
        if left_t is Real or right_t is Real:
            args = left_args if left_t is Real else right_args
            # We want variables, not constants
            args.pop("value",None) if args is not None else None
            retVar = state.getVar(varName='BinOpTemp',varType=Real,kwargs = args)

        else:
            left_args.pop("value",None) if left_args is not None else None
            retVar = state.getVar(varName='BinOpTemp',varType=left_t,kwargs = left_args)

        retVar.increment()

        # Now that we have a clean variable to return, add constraints and return it
        logger.debug("Adding constraint {0} == {1}".format(retVar.getZ3Object(),ret))

        # If it turns out we're dealing with constants, just set it directly.
        if type(ret) in [int,float]:
            retVar.setTo(ret)
        else:
            state.addConstraint(retVar.getZ3Object() == ret)

        #print([x for x in state.solver.assertions()])
        return [retVar.copy()]

    else:
        err = "BinOP: Don't know how to handle variable type {0} at line {1} col {2}".format(t,op.lineno,op.col_offset)
        logger.error(err)
        raise Exception(err)
Esempio n. 9
0
    def check_value(self, val):
        assert val is not None, f"Setting a port's value to None is not allowed"

        # check that we only assign correct values to the ports
        if isinstance(self.domain, list):
            return val in self.domain
        elif self.domain is Types.INTEGER:
            return isinstance(val, int) or z3.is_int_value(val) or z3.is_int(val)
        elif self.domain is Types.REAL:  # z3 types
            return (isinstance(val, numbers.Number) and not isinstance(val, bool)) or z3.is_real(val)
        elif self.domain is Types.INT: # TODO: check also for these types
            return isinstance(val, int)
        elif self.domain is Types.FLOAT: # TODO: check also for these types
            return (isinstance(val, numbers.Number) and not isinstance(val, bool))
        elif self.domain is Types.STRING: # TODO: check also for these types
            return isinstance(val, str)
        elif self.domain is Types.BOOL: # TODO: check also for these types
            return isinstance(val, bool)
        else:
            return False