コード例 #1
0
ファイル: clausecounter.py プロジェクト: cxcfan/PZ3
def count(smt_file):
    formula = z3.parse_smt2_file(smt_file)
    tactic_simp = z3.With(z3.Tactic('simplify'), 'elim_and', True)
    tactic_total = z3.Then(tactic_simp, z3.Tactic('elim-term-ite'))
    tactic_total = z3.Then(tactic_total, z3.Tactic('tseitin-cnf'))
    goals = tactic_total(formula)
    if len(goals) == 1:
        goal = goals[0]
        return len(goal)
    else:
        return -1
コード例 #2
0
    def simplify(self, expr):
        if expr._simplified:
            return expr

        if self._enable_simplification_cache:
            try:
                k = self._simplification_cache_key[expr._cache_key]
                #print "HIT WEAK KEY CACHE"
                return k
            except KeyError:
                pass
            try:
                k = self._simplification_cache_val[expr._cache_key]
                #print "HIT WEAK VALUE CACHE"
                return k
            except KeyError:
                pass

            #print "MISS CACHE"

        l.debug("SIMPLIFYING EXPRESSION")

        #print "SIMPLIFYING"

        expr_raw = self.convert(expr)

        #l.debug("... before: %s (%s)", expr_raw, expr_raw.__class__.__name__)

        if isinstance(expr_raw, z3.BoolRef):
            tactics = z3.Then(z3.Tactic("simplify"), z3.Tactic("propagate-ineqs"), z3.Tactic("propagate-values"), z3.Tactic("unit-subsume-simplify"))
            s = tactics(expr_raw).as_expr()
            n = s.decl().name()

            if n == 'true':
                s = True
            elif n == 'false':
                s = False
        elif isinstance(expr_raw, z3.BitVecRef):
            s = z3.simplify(expr_raw)
        else:
            s = expr_raw

        for b in _eager_backends:
            try:
                o = self.wrap(b.convert(s))
                break
            except BackendError:
                continue
        else:
            o = self._abstract(s)

        #print "SIMPLIFIED"
        #l.debug("... after: %s (%s)", s, s.__class__.__name__)

        o._simplified = Base.FULL_SIMPLIFY

        if self._enable_simplification_cache:
            self._simplification_cache_val[expr._cache_key] = o
            self._simplification_cache_key[expr._cache_key] = o
        return o
コード例 #3
0
def check_equivalence(prog_before, prog_after, allow_undef):
    # The equivalence check of the solver
    # For all input packets and possible table matches the programs should
    # be the same
    z3_prog_before, input_names_before, _ = prog_before
    z3_prog_after, input_names_after, _ = prog_after
    undef_violation = False

    try:
        z3_prog_before = z3.simplify(z3_prog_before)
        z3_prog_after = z3.simplify(z3_prog_after)
        # the equivalence equation
        log.debug("Simplifying equation...")
        tv_equiv = z3.simplify(z3_prog_before != z3_prog_after)
    except z3.Z3Exception as e:
        # Encountered an exception when trying to compare the formulas
        # There might be many reasons for this
        error_string = "Failed to compare Z3 formulas!\nReason: %s" % e
        error_string += "\nPROGRAM BEFORE\n"
        error_string += get_hdr_table(z3_prog_before, input_names_before)
        error_string += "\n\nPROGRAM AFTER\n"
        error_string += get_hdr_table(z3_prog_after, input_names_after)
        log.error(error_string)
        return util.EXIT_VIOLATION
    log.debug("Checking...")
    log.debug(z3.tactics())
    t = z3.Then(
        z3.Tactic("simplify"),
        # z3.Tactic("distribute-forall"),
        # z3.Tactic("ackermannize_bv"),
        # z3.Tactic("bvarray2uf"),
        # z3.Tactic("card2bv"),
        # z3.Tactic("propagate-bv-bounds-new"),
        # z3.Tactic("reduce-bv-size"),
        # z3.Tactic("qe_rec"),
        z3.Tactic("smt"),
    )

    solver = t.solver()
    log.debug(solver.sexpr())
    ret = solver.check(tv_equiv)
    log.debug(tv_equiv)
    log.debug(ret)
    if allow_undef and ret == z3.sat:
        undef_violation = True
        # if we allow undefined changes we need to explicitly recheck
        log.info("Detected difference in undefined behavior. "
                 "Rechecking while substituting undefined variables.")
        ret = undef_check(solver, z3_prog_before, z3_prog_after)

    if ret == z3.sat:
        print_validation_error(prog_before, prog_after, solver.model())
        return util.EXIT_VIOLATION
    elif ret == z3.unknown:
        log.error("Solution unknown! There might be a problem...")
        return util.EXIT_VIOLATION
    else:
        if undef_violation:
            return util.EXIT_UNDEF
        return util.EXIT_SUCCESS
コード例 #4
0
ファイル: luigi-qif.py プロジェクト: GaloisInc/luigi-qif
def convert_to_dimacs(goal, project_onto):
    '''
    Convert a Z3 goal into DIMACS so that ApproxMC can understand it.
    '''
    # Based on https://stackoverflow.com/a/33860849
    bits = set()
    for var in project_onto:
        nbits = var.sort().size()
        # Give a name to each bit of each bitvector
        for bit_index in range(nbits):
            name = '%s_%d' % (var, bit_index)
            bits.add(name)
            bit = z3.Bool(name)
            mask = z3.BitVecVal(1 << bit_index, nbits)
            goal.add(bit == ((var & mask) == mask))
    # z3.With(..., args) provides arguments to the "..." tactic.
    tactic = z3.Then(
        'simplify',
        z3.With(
            z3.Tactic('bit-blast'),
            blast_full=True,
            blast_quant=True,
        ),
        'blast-term-ite',
        z3.With(
            z3.Tactic('propagate-values'),
            blast_eq_value=True,
            blast_distinct=True,
        ),
        z3.With(
            z3.Tactic('simplify'),
            blast_eq_value=True,
        ),
        'blast-term-ite',
        'tseitin-cnf',
        'blast-term-ite',
    )
    expr = tactic(goal)
    assert len(expr) == 1
    expr = expr[0]
    dimacs = expr.dimacs()
    # ind is the Independent Set
    ind = set()
    # Parse the dimacs to determine how Z3 maps the boolean variables to the
    # dimacs variable number
    lines = dimacs.split('\n')
    for line in lines:
        if not line.startswith('c '):
            # It's not a comment.
            continue
        # Otherwise assume that this line maps variables to names
        parts = line.split()
        _, number, var = parts
        if var in bits:
            bits.remove(var)
            ind.add(number)
    # TODO: will this always be true?
    assert len(bits) == 0, repr(bits)
    return 'c ind %s 0\n%s\n' % (' '.join(ind), dimacs)
コード例 #5
0
ファイル: backend_z3.py プロジェクト: hestati63/MetaSE
 def _search_simplify_tactics(self):
     try:
         return self._tls.search_simplify_tactics
     except AttributeError:
         tactics = z3.Then(z3.Tactic("simplify", ctx=self._context),
                           z3.Tactic("aig", ctx=self._context),
                           ctx=self._context)
         self._tls.search_simplify_tactics = tactics
         return self._tls.search_simplify_tactics
コード例 #6
0
def build_test(config, main_formula, cond_tuple, pkt_range):
    permut_conds, avoid_conds, undefined_conds = cond_tuple

    # now we actually verify that we can find an input
    s = z3.Solver()
    # bind the output constant to the output of the main program
    output_const = z3.Const("output", main_formula.sort())
    s.add(main_formula == output_const)

    undefined_matches = z3.And(*undefined_conds)
    s.add(undefined_matches)

    avoid_matches = z3.Not(z3.Or(*avoid_conds))
    s.add(avoid_matches)
    # we need this tactic to find out which values will be undefined at the end
    # or which headers we expect to be invalid
    # the tactic effectively simplifies the formula to a single expression
    # under the constraints we have defined
    t = z3.Then(z3.Tactic("propagate-values"),
                z3.Tactic("ctx-solver-simplify"), z3.Tactic("elim-and"))
    # this is the test string we assemble
    stf_str = ""
    for permut in permut_conds:
        s.push()
        s.add(permut)
        log.info("Checking for solution...")
        ret = s.check()
        if ret == z3.sat:
            log.info("Found a solution!")
            # get the model
            m = s.model()
            # this does not work well yet... desperate hack
            # FIXME: Figure out a way to solve this, might not be solvable
            g = z3.Goal()
            g.add(main_formula == output_const, avoid_matches,
                  undefined_matches, z3.And(*permut))
            log.debug(z3.tactics())
            log.info("Inferring simplified input and output")
            constrained_output = t.apply(g)
            log.info("Inferring dont-care map...")
            # FIXME: horrible
            output_var = constrained_output[0][0].children()[0]
            dont_care_map = get_dont_care_map(config, output_var, pkt_range)
            input_hdr = m[z3.Const(config["ingress_var"], output_const.sort())]
            output_hdr = m[output_const]
            log.debug("Output header: %s", output_hdr)
            log.debug("Input header: %s", input_hdr)
            flat_input = input_hdr.children()[pkt_range]
            flat_output = output_hdr.children()[pkt_range]
            stf_str += get_stf_str(flat_input, flat_output, dont_care_map)
            stf_str += "\n"
        else:
            # FIXME: This should be an error
            log.warning("No valid input could be found!")
        s.pop()
    # the final stf string lists all the interesting packets to test
    return stf_str
コード例 #7
0
    def simplify(self, expr):
        if expr._simplified:
            return expr

        if self._enable_simplification_cache:
            try:
                k = self._simplification_cache_key[expr._cache_key]
                #print "HIT WEAK KEY CACHE"
                return k
            except KeyError:
                pass
            try:
                k = self._simplification_cache_val[expr._cache_key]
                #print "HIT WEAK VALUE CACHE"
                return k
            except KeyError:
                pass

            #print "MISS CACHE"

        l.debug("SIMPLIFYING EXPRESSION")

        #print "SIMPLIFYING"

        expr_raw = self.convert(expr)

        #l.debug("... before: %s (%s)", expr_raw, expr_raw.__class__.__name__)

        #s = expr_raw
        if isinstance(expr_raw, z3.BoolRef):
            tactics = z3.Then(
                z3.Tactic("simplify", ctx=self._context),
                z3.Tactic("propagate-ineqs", ctx=self._context),
                z3.Tactic("propagate-values", ctx=self._context),
                z3.Tactic("unit-subsume-simplify", ctx=self._context),
                z3.Tactic("aig", ctx=self._context),
                ctx=self._context
            )
            s = tactics(expr_raw).as_expr()
            #n = s.decl().name()
            #if n == 'true':
            #    s = True
            #elif n == 'false':
            #    s = False
        elif isinstance(expr_raw, z3.BitVecRef):
            s = z3.simplify(expr_raw)
        else:
            s = expr_raw

        o = self._abstract(s)
        o._simplified = Base.FULL_SIMPLIFY

        if self._enable_simplification_cache:
            self._simplification_cache_val[expr._cache_key] = o
            self._simplification_cache_key[expr._cache_key] = o
        return o
コード例 #8
0
 def __init__(self, eqns=None, tactics=None, timeout=None):
     self.eqns = []
     self.locs = []
     if tactics:
         s = z3.TryFor(z3.Then(*tactics), 1000).solver()
     else:
         s = z3.Solver()
     if timeout: s.set(timeout=1000)
     self.solver = s
     if eqns: self.add(eqns)
     self._ctr = 0
コード例 #9
0
    def get_boolref_tactics(self):
        tactics = z3.Then(
            z3.Tactic("simplify"),
            z3.Tactic("sat-preprocess"),
            z3.Tactic("cofactor-term-ite"),
            z3.Tactic("propagate-ineqs"),
            z3.Tactic("propagate-values"),
            z3.Tactic("unit-subsume-simplify"),
            z3.Tactic("aig"),
        )

        return tactics
コード例 #10
0
 def _boolref_tactics(self):
     try:
         return self._tls.boolref_tactics
     except AttributeError:
         tactics = z3.Then(z3.Tactic("simplify", ctx=self._context),
                           z3.Tactic("propagate-ineqs", ctx=self._context),
                           z3.Tactic("propagate-values", ctx=self._context),
                           z3.Tactic("unit-subsume-simplify",
                                     ctx=self._context),
                           z3.Tactic("aig", ctx=self._context),
                           ctx=self._context)
         self._tls.boolref_tactics = tactics
         return self._tls.boolref_tactics
コード例 #11
0
def calculate(input_smt):
    formula = z3.parse_smt2_file(input_smt)
    tactic_simp = z3.With(z3.Tactic('simplify'), 'elim_and', True)
    tactic_total = z3.Then(tactic_simp, z3.Tactic('elim-term-ite'))
    tactic_total = z3.Then(tactic_total, z3.Tactic('tseitin-cnf'))
    goals = tactic_total.apply(formula)
    if len(goals) == 1:
        goal = goals[0]
        # the goal is the list of constraints, and conjunction of which is equivalent to the original problem
        manager = compute(goal)
        # compute sparseness
        num_visible = manager.get_visible_size()
        num_var = manager.get_var_size()
        num_total = manager.get_total_size()
        num_min = manager.get_maximum_clause_size()
        sparse = (num_visible - num_min) / (num_total - num_min)
        factor_min = math.ceil((1 + math.sqrt(1 + 8 * num_visible)) / 2)
        factor_max = 2 * num_total
        factor = (num_var - factor_min) / (factor_max - factor_min)
        return sparse, factor
    else:
        return '*', '*'
コード例 #12
0
ファイル: formula.py プロジェクト: RobinDavid/pydimacs
    def __init__(self):
        """
        Class construction. A formula is meant to be instanciated
        via the static methods from_z3, from_smt2_file, from_dimacs_string
        and from_dimacs_file.
        """
        self.goal = z3.Goal()
        self.tactics = z3.Then('simplify', 'bit-blast', 'tseitin-cnf')
        self.subgoal = None  # keep it in case of
        # Goal is a collection of constraints we want to find a solution or show to be unsatisfiable (infeasible).
        # Goals are processed using Tactics. A Tactic transforms a goal into a set of subgoals.
        # A goal has a solution if one of its subgoals has a solution.
        # A goal is unsatisfiable if all subgoals are unsatisfiable.

        self.variables_num = None
        self.clauses_num = None
        self.clauses = []
コード例 #13
0
ファイル: smt_wrapper.py プロジェクト: slahiruk/Charm
 def __init__(self, types, cons):
     super().__init__()
     assert isinstance(types, dict), 'Types for SMT must be a dictionary'
     assert isinstance(cons, list), 'Constraints for SMT must be a list'
     self.types = types
     self.cons = cons
     self.asmpts = []
     # Some may call this the dark side but
     # put SMT variables in object locals, so that we can refer to them
     # at other places.
     single = 'z3.Float32()'
     double = 'z3.Float64()'
     BV32 = 'z3.BitVecSort(32)'
     BV64 = 'z3.BitVecSort(64)'
     RNE = 'z3.RNE()'
     for v in list(self.types.keys()):
         assert v not in vars(self)
         if self.types[v] == 'float':
             dym_str = 'vars(self)["{}"] = z3.Const("{}", {})'.format(
                 v, v, double)
         else:
             assert self.types[v] == 'int'
             dym_str = 'vars(self)["{}"] = z3.fpSignedToFP({}, z3.Const("{}", {}), {})'.format(
                 v, RNE, v, BV64, double)
         exec(dym_str)
     # TODO Cannot find reference to Tactic, check for problems
     t1 = z3.Tactic('simplify')
     t2 = z3.Tactic('solve-eqs')
     t3 = z3.Tactic('split-clause')
     t4 = z3.Tactic('qffpbv')
     t5 = z3.Tactic('qfnra-nlsat')
     t6 = z3.Tactic('normalize-bounds')
     t7 = z3.Tactic('smt')
     goal = z3.Then(z3.AndThen(t1, t2, t6), t4)
     # goal = z3.AndThen(t1, t2, t6)
     self.solver = goal.solver()
     for con in self.cons:
         trans_con = self.__transform(con)
         self.solver.add(trans_con)
コード例 #14
0
ファイル: test_negate.py プロジェクト: teobaluta/NPAQ
    def test_example_negate_self(self):
        if not os.path.exists(definitions.EXAMPLE_PATH):
            print('{} does not exist! Exiting...'.format(
                definitions.EXAMPLE_PATH))
            exit(1)

        subprocess.call(
            [definitions.EXAMPLE_PATH,
             os.path.abspath(TEST1_FILE)])

        z3_fml, seen_lits = utils.dimacs2fml(TEST1_FILE)
        # print('[{}] z3 formula: {}'.format(self._testMethodName, z3_fml))
        print('[{}] #vars: {}'.format(self._testMethodName, seen_lits))
        self.assertEqual(len(seen_lits), 17)

        g = z3.Goal()
        neg_z3_fml = z3.Not(z3.And(z3_fml))
        # print('[{}] Negated formula: {}'.format(self._testMethodName, neg_z3_fml))
        g.add(neg_z3_fml)
        t = z3.Then('simplify', 'tseitin-cnf')
        neg_cnf = t(g)[0]
        #print('[{}] Negated CNF: {}'.format(self._testMethodName, neg_cnf))

        utils.translate2dimacs(neg_cnf,
                               len(seen_lits),
                               TEST1_FILE,
                               append_to_file=True)
        num_vars, num_clauses = utils.parse_dimacs_header(TEST1_FILE)

        print('[{}] Formula and not formula num_vars {}, num_clauses \
              {}'.format(self._testMethodName, num_vars, num_clauses))

        fml, seen_lits = utils.dimacs2fml(TEST1_FILE)
        s = z3.Solver()
        s.add(fml)
        sol = s.check()
        self.assertEqual(sol, z3.unsat)
コード例 #15
0
ファイル: smt_verify_wp.py プロジェクト: rnbguy/svss
#!/usr/bin/python3

import pycparser as pycp
import z3
import sys

t_qe = z3.Tactic('qe')
t = z3.Repeat(
    z3.Then("simplify", "propagate-ineqs", "propagate-values",
            "unit-subsume-simplify"))
t_qe_ = z3.Then(t_qe, t)


def gen_smt_expr(ast):
    if isinstance(ast, pycp.c_ast.Constant):
        return z3.BitVecVal(ast.value, 32)
    elif isinstance(ast, pycp.c_ast.ID):
        return vars[ast.name]
    elif isinstance(ast, pycp.c_ast.UnaryOp):
        if ast.op == "-":
            return "-" + gen_smt_expr(ast.expr)
        if ast.op == "!":
            return z3.Not(gen_smt_expr(ast.expr))
    elif isinstance(ast, pycp.c_ast.BinaryOp):
        lexp = gen_smt_expr(ast.left)
        rexp = gen_smt_expr(ast.right)
        if ast.op == "+":
            return lexp + rexp
        if ast.op == "-":
            return lexp - rexp
        elif ast.op == "*":
コード例 #16
0
#!/usr/bin/python3

import pycparser as pycp
import z3
import sys
import random

t = z3.Repeat(
    z3.Then("propagate-values", "propagate-ineqs", "unit-subsume-simplify",
            "propagate-bv-bounds", "simplify"))
t_qe = z3.OrElse(z3.Then(z3.TryFor('qe', 1000), z3.TryFor('qe2', 1000)),
                 'skip')


def gen_smt_expr(ast):
    if isinstance(ast, pycp.c_ast.Constant):
        return z3.BitVecVal(ast.value, 32)
    elif isinstance(ast, pycp.c_ast.ID):
        return vars[ast.name]
    elif isinstance(ast, pycp.c_ast.UnaryOp):
        if ast.op == "-":
            return "-" + gen_smt_expr(ast.expr)
        if ast.op == "!":
            return z3.Not(gen_smt_expr(ast.expr))
    elif isinstance(ast, pycp.c_ast.BinaryOp):
        lexp = gen_smt_expr(ast.left)
        rexp = gen_smt_expr(ast.right)
        if ast.op == "+":
            return lexp + rexp
        if ast.op == "-":
            return lexp - rexp
コード例 #17
0
def solve(threshold):

    MAX_TURN = 42

    s = z3.Goal()  # z3.Solver()

    bb_player = [z3.BitVec(f"bb_player_{i}", 64) for i in range(MAX_TURN + 2)]
    bb_opponent = [
        z3.BitVec(f"bb_opponent_{i}", 64) for i in range(MAX_TURN + 2)
    ]
    pop_move = [z3.BitVec(f"pop_move_{i}", 64) for i in range(MAX_TURN + 2)]

    directions1 = [z3.BitVec(f"directions1_{i}", 64) for i in range(4)]
    directions2 = [z3.BitVec(f"directions2_{i}", 64) for i in range(4)]

    flip_const1 = [z3.BitVec(f"flip_const1_{i}", 64) for i in range(4)]
    flip_const2 = [z3.BitVec(f"flip_const2_{i}", 64) for i in range(4)]
    flip_const3 = [z3.BitVec(f"flip_const3_{i}", 64) for i in range(4)]

    num_zero = z3.BitVec("num_zero", 64)
    num_one = z3.BitVec("num_one", 64)

    num_threshold = z3.BitVec("num_threshold", 64)

    s.add(bb_player[0] == 0x0000001008000000,
          bb_opponent[0] == 0x0000000810000000, pop_move[0] == 0,
          directions1[0] == 1, directions1[1] == 7, directions1[2] == 8,
          directions1[3] == 9, directions2[0] == 2, directions2[1] == 14,
          directions2[2] == 16, directions2[3] == 18,
          flip_const1[0] == 0xFFFFFFFFFFFFFFFF,
          flip_const1[1] == 0x7E7E7E7E7E7E7E7E,
          flip_const1[2] == 0x7E7E7E7E7E7E7E7E,
          flip_const1[3] == 0x7E7E7E7E7E7E7E7E,
          flip_const2[0] == 0x0080808080808080,
          flip_const2[1] == 0x7F00000000000000,
          flip_const2[2] == 0x0102040810204000,
          flip_const2[3] == 0x0040201008040201,
          flip_const3[0] == 0x0101010101010100,
          flip_const3[1] == 0x00000000000000FE,
          flip_const3[2] == 0x0002040810204080,
          flip_const3[3] == 0x8040201008040200, num_zero == 0, num_one == 1,
          num_threshold == threshold)

    for turn in range(MAX_TURN + 1):
        bb_occupied = z3.BitVec(f"bb_occupied_{turn}", 64)
        bb_empty = z3.BitVec(f"bb_empty_{turn}", 64)
        masked_bb_opponent = z3.BitVec(f"masked_bb_opponent_{turn}", 64)

        movemask = [z3.BitVec(f"movemask_{turn}_{i}", 64) for i in range(4)]

        flip_l_0 = [z3.BitVec(f"flip_l_0_{turn}_{i}", 64) for i in range(4)]
        flip_r_0 = [z3.BitVec(f"flip_r_0_{turn}_{i}", 64) for i in range(4)]
        flip_l_1 = [z3.BitVec(f"flip_l_1_{turn}_{i}", 64) for i in range(4)]
        flip_r_1 = [z3.BitVec(f"flip_r_1_{turn}_{i}", 64) for i in range(4)]
        flip_l_2 = [z3.BitVec(f"flip_l_2_{turn}_{i}", 64) for i in range(4)]
        flip_r_2 = [z3.BitVec(f"flip_r_2_{turn}_{i}", 64) for i in range(4)]
        flip_l_3 = [z3.BitVec(f"flip_l_3_{turn}_{i}", 64) for i in range(4)]
        flip_r_3 = [z3.BitVec(f"flip_r_3_{turn}_{i}", 64) for i in range(4)]
        mask_l = [z3.BitVec(f"mask_l_{turn}_{i}", 64) for i in range(4)]
        mask_r = [z3.BitVec(f"mask_r_{turn}_{i}", 64) for i in range(4)]

        some_moves = [
            z3.BitVec(f"some_moves_{turn}_{i}", 64) for i in range(4)
        ]
        all_moves = z3.BitVec(f"all_moves_{turn}", 64)
        pop_now = z3.BitVec(f"pop_now_{turn}", 64)

        popcnt_move_tmp1 = z3.BitVec(f"popcnt_move_tmp1_{turn}", 64)
        popcnt_move_tmp2 = z3.BitVec(f"popcnt_move_tmp2_{turn}", 64)

        s.add(bb_occupied == bb_player[turn] | bb_opponent[turn],
              bb_empty == bb_occupied ^ 0xFFFFFFFFFFFFFFFF,
              masked_bb_opponent == bb_opponent[turn] & 0x7E7E7E7E7E7E7E7E,
              movemask[0] == masked_bb_opponent,
              movemask[1] == masked_bb_opponent,
              movemask[2] == bb_opponent[turn],
              movemask[3] == masked_bb_opponent)
        s.add([
            z3.And(flip_l_0[i] == (movemask[i]
                                   & (bb_player[turn] << directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_0[i] == (movemask[i]
                                   & z3.LShR(bb_player[turn], directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_l_1[i] == (
                flip_l_0[i] | (movemask[i] & (flip_l_0[i] << directions1[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_1[i] == (
                flip_r_0[i]
                | (movemask[i] & z3.LShR(flip_r_0[i], directions1[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(mask_l[i] == (movemask[i]
                                 & (movemask[i] << directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(mask_r[i] == (movemask[i]
                                 & z3.LShR(movemask[i], directions1[i])))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_l_2[i] == (
                flip_l_1[i] | (mask_l[i] & (flip_l_1[i] << directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_2[i] == (
                flip_r_1[i]
                | (mask_r[i] & z3.LShR(flip_r_1[i], directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_l_3[i] == (
                flip_l_2[i] | (mask_l[i] & (flip_l_2[i] << directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(flip_r_3[i] == (
                flip_r_2[i]
                | (mask_r[i] & z3.LShR(flip_r_2[i], directions2[i]))))
            for i in range(4)
        ])
        s.add([
            z3.And(some_moves[i] == ((flip_l_3[i] << directions1[i])
                                     | z3.LShR(flip_r_3[i], directions1[i])))
            for i in range(4)
        ])
        s.add(
            all_moves == (some_moves[0] | some_moves[1] | some_moves[2]
                          | some_moves[3]) & bb_empty,
            popcnt_move_tmp1 == all_moves -
            (z3.LShR(all_moves, 1) & 0x7777777777777777) -
            (z3.LShR(all_moves, 2) & 0x3333333333333333) -
            (z3.LShR(all_moves, 3) & 0x1111111111111111), popcnt_move_tmp2 == (
                (popcnt_move_tmp1 + z3.LShR(popcnt_move_tmp1, 4))
                & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101, pop_now == z3.LShR(
                    popcnt_move_tmp2,
                    56), pop_move[turn + 1] == z3.If(pop_now > pop_move[turn],
                                                     pop_now, pop_move[turn]))

        move_onebit = z3.BitVec(f"move_onebit_{turn}", 64)
        move_bsf_tmp = [
            z3.BitVec(f"move_bsf_tmp_{turn}_{i}", 64) for i in range(9)
        ]
        move_pos = z3.BitVec(f"move_pos_{turn}", 64)

        s.add(
            move_onebit & (move_onebit - 1) == 0, move_onebit
            & all_moves == move_onebit, move_bsf_tmp[0] == move_onebit - 1,
            move_bsf_tmp[1] == move_bsf_tmp[0] | z3.LShR(move_bsf_tmp[0], 1),
            move_bsf_tmp[2] == move_bsf_tmp[1] | z3.LShR(move_bsf_tmp[1], 2),
            move_bsf_tmp[3] == move_bsf_tmp[2] | z3.LShR(move_bsf_tmp[2], 4),
            move_bsf_tmp[4] == move_bsf_tmp[3] | z3.LShR(move_bsf_tmp[3], 8),
            move_bsf_tmp[5] == move_bsf_tmp[4] | z3.LShR(move_bsf_tmp[4], 16),
            move_bsf_tmp[6] == move_bsf_tmp[5] | z3.LShR(move_bsf_tmp[5], 32),
            move_bsf_tmp[7] == move_bsf_tmp[6] -
            (z3.LShR(move_bsf_tmp[6], 1) & 0x7777777777777777) -
            (z3.LShR(move_bsf_tmp[6], 2) & 0x3333333333333333) -
            (z3.LShR(move_bsf_tmp[6], 3) & 0x1111111111111111),
            move_bsf_tmp[8] == ((move_bsf_tmp[7] + z3.LShR(move_bsf_tmp[7], 4))
                                & 0x0F0F0F0F0F0F0F0F) * 0x0101010101010101,
            move_pos == z3.LShR(move_bsf_tmp[8], 56))

        OM = [z3.BitVec(f"OM_{turn}_{i}", 64) for i in range(4)]
        mask1 = [z3.BitVec(f"mask1_{turn}_{i}", 64) for i in range(4)]
        upperbit_argument = [
            z3.BitVec(f"upperbit_argument_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp1 = [
            z3.BitVec(f"upperbit_tmp1_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp2 = [
            z3.BitVec(f"upperbit_tmp2_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp3 = [
            z3.BitVec(f"upperbit_tmp3_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp4 = [
            z3.BitVec(f"upperbit_tmp4_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp5 = [
            z3.BitVec(f"upperbit_tmp5_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp6 = [
            z3.BitVec(f"upperbit_tmp6_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp7 = [
            z3.BitVec(f"upperbit_tmp7_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp8 = [
            z3.BitVec(f"upperbit_tmp8_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp9 = [
            z3.BitVec(f"upperbit_tmp9_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_tmp10 = [
            z3.BitVec(f"upperbit_tmp10_{turn}_{i}", 64) for i in range(4)
        ]
        upperbit_result = [
            z3.BitVec(f"upperbit_result_{turn}_{i}", 64) for i in range(4)
        ]
        outflank1 = [z3.BitVec(f"outflank1_{turn}_{i}", 64) for i in range(4)]
        flipped1 = [z3.BitVec(f"flipped1_{turn}_{i}", 64) for i in range(4)]

        mask2 = [z3.BitVec(f"mask2_{turn}_{i}", 64) for i in range(4)]
        outflank2 = [z3.BitVec(f"outflank2_{turn}_{i}", 64) for i in range(4)]
        nonzero = [z3.BitVec(f"nonzero_{turn}_{i}", 64) for i in range(4)]
        flipped2 = [z3.BitVec(f"flipped2_{turn}_{i}", 64) for i in range(4)]

        bb_flip = z3.BitVec(f"bb_flip_{turn}", 64)
        next_player_tmp = z3.BitVec(f"next_player_tmp_{turn}", 64)
        next_opponent_tmp = z3.BitVec(f"next_opponent_tmp_{turn}", 64)

        s.add([
            z3.And(OM[i] == (bb_opponent[turn] & flip_const1[i]))
            for i in range(4)
        ])
        s.add([
            z3.And(mask1[i] == z3.LShR(flip_const2[i], 63 - move_pos))
            for i in range(4)
        ])

        s.add([
            z3.And(upperbit_argument[i] == (~OM[i]) & mask1[i])
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp1[i] == upperbit_argument[i]
                   | z3.LShR(upperbit_argument[i], 1)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp2[i] == upperbit_tmp1[i]
                   | z3.LShR(upperbit_tmp1[i], 2)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp3[i] == upperbit_tmp2[i]
                   | z3.LShR(upperbit_tmp2[i], 4)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp4[i] == (~z3.LShR(upperbit_tmp3[i], 1))
                   & upperbit_tmp3[i]) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp5[i] == (upperbit_tmp4[i] << 32)
                   | z3.LShR(upperbit_tmp4[i], 32)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp6[i] == (
                (upperbit_tmp5[i] & 0x0000FFFF0000FFFF) << 16)
                   | z3.LShR(upperbit_tmp5[i] & 0xFFFF0000FFFF0000, 16))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp7[i] == (
                (upperbit_tmp6[i] & 0x00FF00FF00FF00FF) << 8)
                   | z3.LShR(upperbit_tmp6[i] & 0xFF00FF00FF00FF00, 8))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp8[i] == upperbit_tmp7[i] & (-upperbit_tmp7[i]))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp9[i] == (upperbit_tmp8[i] << 32)
                   | z3.LShR(upperbit_tmp8[i], 32)) for i in range(4)
        ])
        s.add([
            z3.And(upperbit_tmp10[i] == (
                (upperbit_tmp9[i] & 0x0000FFFF0000FFFF) << 16)
                   | z3.LShR(upperbit_tmp9[i] & 0xFFFF0000FFFF0000, 16))
            for i in range(4)
        ])
        s.add([
            z3.And(upperbit_result[i] == (
                (upperbit_tmp10[i] & 0x00FF00FF00FF00FF) << 8)
                   | z3.LShR(upperbit_tmp10[i] & 0xFF00FF00FF00FF00, 8))
            for i in range(4)
        ])

        s.add([
            z3.And(outflank1[i] == upperbit_result[i] & bb_player[turn])
            for i in range(4)
        ])
        s.add([
            z3.And(flipped1[i] == ((-outflank1[i]) << 1) & mask1[i])
            for i in range(4)
        ])

        s.add(
            [z3.And(mask2[i] == flip_const3[i] << move_pos) for i in range(4)])
        s.add([
            z3.And(outflank2[i] == ((OM[i] | (~mask2[i])) + 1) & mask2[i]
                   & bb_player[turn]) for i in range(4)
        ])
        s.add([
            z3.And(nonzero[i] == z3.If(outflank2[i] == 0, num_zero, num_one))
            for i in range(4)
        ])
        s.add([
            z3.And(flipped2[i] == (outflank2[i] - nonzero[i]) & mask2[i])
            for i in range(4)
        ])
        s.add(
            bb_flip == flipped1[0] | flipped1[1] | flipped1[2] | flipped1[3]
            | flipped2[0] | flipped2[1] | flipped2[2] | flipped2[3],
            next_player_tmp == bb_opponent[turn] ^ bb_flip,
            next_opponent_tmp == bb_player[turn] ^ (bb_flip | move_onebit),
            bb_player[turn + 1] == z3.If(move_onebit == 0, bb_opponent[turn],
                                         next_player_tmp),
            bb_opponent[turn + 1] == z3.If(move_onebit == 0, bb_player[turn],
                                           next_opponent_tmp))

    s.add(pop_move[MAX_TURN + 1] >= num_threshold)

    t = z3.Then('simplify', 'bit-blast', 'solve-eqs', 'tseitin-cnf')
    subgoal = t(s)
    assert len(subgoal) == 1

    return subgoal[0]
コード例 #18
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
コード例 #19
0
#!/usr/bin/python3

import pycparser as pycp
import z3
import sys

t_qe = z3.Tactic('qe')
t = z3.Repeat(z3.Then("simplify", "propagate-ineqs",
                      "propagate-values", "unit-subsume-simplify",
                      z3.OrElse("split-clause", "skip")))
t_qe_ = z3.Then(t_qe, t)


def gen_smt_expr(ast):
    if isinstance(ast, pycp.c_ast.Constant):
        return z3.IntVal(ast.value)
    elif isinstance(ast, pycp.c_ast.ID):
        return vars[ast.name]
    elif isinstance(ast, pycp.c_ast.UnaryOp):
        if ast.op == "-":
            return "-" + gen_smt_expr(ast.expr)
        if ast.op == "!":
            return z3.Not(gen_smt_expr(ast.expr))
    elif isinstance(ast, pycp.c_ast.BinaryOp):
        lexp = gen_smt_expr(ast.left)
        rexp = gen_smt_expr(ast.right)
        if ast.op == "+":
            return lexp + rexp
        if ast.op == "-":
            return lexp - rexp
        elif ast.op == "*":
コード例 #20
0
 def write(self):
     t = z3.Then('simplify', 'bit-blast', 'tseitin-cnf')
     subgoal = t(self.slvr)
     assert len(subgoal) == 1
     open('cnf.dimacs', 'w').write(subgoal[0].dimacs())
コード例 #21
0
def check_equivalence(prog_before, prog_after, allow_undef):
    # The equivalence check of the solver
    # For all input packets and possible table matches the programs should
    # be the same
    try:
        # the equivalence equation
        log.debug("Simplifying equation...")
        tv_equiv = z3.simplify(prog_before != prog_after)
    except z3.Z3Exception as e:
        prog_before_simpl = z3.simplify(prog_before)
        prog_after_simpl = z3.simplify(prog_after)
        log.error("Failed to compare z3 formulas!\nReason: %s", e)
        log.error("PROGRAM BEFORE\n%s", prog_before_simpl)
        log.error("PROGRAM AFTER\n%s", prog_after_simpl)
        return util.EXIT_VIOLATION
    log.debug("Checking...")
    log.debug(z3.tactics())
    t = z3.Then(
        z3.Tactic("simplify"),
        # z3.Tactic("distribute-forall"),
        # z3.Tactic("ackermannize_bv"),
        # z3.Tactic("bvarray2uf"),
        # z3.Tactic("card2bv"),
        # z3.Tactic("propagate-bv-bounds-new"),
        # z3.Tactic("reduce-bv-size"),
        # z3.Tactic("qe_rec"),
        z3.Tactic("smt"),
    )

    s = t.solver()
    log.debug(s.sexpr())
    ret = s.check(tv_equiv)
    log.debug(tv_equiv)
    log.debug(ret)
    if allow_undef and ret == z3.sat:
        prog_before = z3.simplify(prog_before)
        prog_after = z3.simplify(prog_after)
        log.info("Detected difference in undefined behavior. "
                 "Rechecking with undefined variables ignored.")
        taints = set()
        log.info("Preprocessing...")
        prog_before, _ = substitute_taint(prog_before, taints)
        log.info("Checking...")
        tv_equiv = prog_before != prog_after
        if taints:
            tv_equiv = z3.ForAll(list(taints), tv_equiv)
        # check equivalence of the modified clause
        ret = s.check(tv_equiv)

    if ret == z3.sat:
        prog_before_simpl = z3.simplify(prog_before)
        prog_after_simpl = z3.simplify(prog_after)
        log.error("Detected an equivalence violation!")
        log.error("PROGRAM BEFORE\n%s", prog_before_simpl)
        log.error("PROGRAM AFTER\n%s", prog_after_simpl)
        log.error("Proposed solution:")
        log.error(s.model())
        return util.EXIT_VIOLATION
    elif ret == z3.unknown:
        prog_before_simpl = z3.simplify(prog_before)
        prog_after_simpl = z3.simplify(prog_after)
        log.error("Solution unknown! There might be a problem...")
        return util.EXIT_VIOLATION
    else:
        return util.EXIT_SUCCESS
コード例 #22
0
def perform_blackbox_test(config):
    out_dir = config["out_dir"]
    p4_input = config["p4_input"]
    if out_dir == OUT_DIR:
        out_dir = out_dir.joinpath(p4_input.stem)
    util.check_dir(out_dir)
    util.copy_file(p4_input, out_dir)
    config["out_dir"] = out_dir
    config["p4_input"] = p4_input

    # get the semantic representation of the original program
    z3_main_prog, result = get_semantics(config)
    if result != util.EXIT_SUCCESS:
        return result
    # now we actually verify that we can find an input
    s = z3.Solver()
    # we currently ignore all other pipelines and focus on the ingress pipeline
    main_formula = z3.simplify(z3_main_prog[config["pipe_name"]])
    # this util might come in handy later.
    # z3.z3util.get_vars(main_formula)
    conditions = get_branch_conditions(main_formula)
    log.info(conditions)
    cond_tuple = dissect_conds(config, conditions)
    permut_conds, avoid_conds, undefined_conds = cond_tuple
    log.info("Computing permutations...")
    # FIXME: This does not scale well...
    # FIXME: This is a complete hack, use a more sophisticated method
    permuts = [[f(var) for var, f in zip(permut_conds, x)]
               for x in itertools.product([z3.Not, lambda x: x],
                                          repeat=len(permut_conds))]
    output_const = z3.Const("output", main_formula.sort())
    # bind the output constant to the output of the main program
    s.add(main_formula == output_const)
    # all keys must be false for now
    # FIXME: Some of them should be usable
    log.info(15 * "#")
    log.info("Undefined conditions:")
    s.add(z3.And(*undefined_conds))
    for cond in undefined_conds:
        log.info(cond)
    log.info("Conditions to avoid:")
    s.add(z3.Not(z3.Or(*avoid_conds)))
    for cond in avoid_conds:
        log.info(cond)
    log.info("Permissible permutations:")
    for cond in permuts:
        log.info(cond)
    log.info(15 * "#")
    for permut in permuts:
        s.push()
        s.add(permut)
        log.info("Checking for solution...")
        ret = s.check()
        if ret == z3.sat:
            log.info("Found a solution!")
            # get the model
            m = s.model()
            # this does not work well yet... desperate hack
            # FIXME: Figure out a way to solve this, might not be solvable
            avoid_matches = z3.Not(z3.Or(*avoid_conds))
            undefined_matches = z3.And(*undefined_conds)
            permut_match = z3.And(*permut)
            g = z3.Goal()
            g.add(main_formula == output_const, avoid_matches,
                  undefined_matches, permut_match)
            log.debug(z3.tactics())
            t = z3.Then(z3.Tactic("propagate-values"),
                        z3.Tactic("ctx-solver-simplify"),
                        z3.Tactic("elim-and"))
            log.info("Inferring simplified input and output")
            constrained_output = t.apply(g)
            log.info("Inferring dont-care map...")
            output_var = constrained_output[0][0]
            dont_care_map = get_dont_care_map(config, output_var)
            result = check_with_stf(config, m, output_const, dont_care_map)
            if result != util.EXIT_SUCCESS:
                return result
        else:
            # FIXME: This should be an error
            log.warning("No valid input could be found!")
        s.pop()
    return result