Ejemplo n.º 1
0
def tryAndVerifyWithSplitterPreds(bbs,
                                  loop,
                                  old_sound_invs,
                                  boogie_invs,
                                  splitterPreds,
                                  partialInvs,
                                  timeout=None):
    """ Wrapper around tryAndVerify_impl that adds implication with
        the splitter predicates to all candidate invariants. Returns
          ((p1_overfit, p2_overfit), (p1_nonindg, p2_nonind), sound, violations)

        Where

          p1_overfit, p2_ovefit are lists of pairs of overfittted invariants
                    and their respective counterexamples from passes 1 and 2
          p1_nonind, p2_ovefit are lists of pairs of noninductive invariants
                    and their respective counterexamples from passes 1 and 2
          sound is a set of sound invariants
          violations is a list of any safety violations permitted by the sound
          invariants
    """
    assert isinstance(old_sound_invs, set)
    assert isinstance(boogie_invs, set)
    assert isinstance(partialInvs, list)
    assert isinstance(splitterPreds, list)

    initial_sound = old_sound_invs.union(partialInvs)

    # First lets find the invariants that are sound without implication
    p1_overfitted, p1_nonind, p1_sound, violations =\
      tryAndVerify_impl(bbs, loop, initial_sound, boogie_invs, timeout)
    p1_sound = \
        set([x for x in p1_sound \
               if not conservative_tautology(expr_to_z3(x, AllIntTypeEnv()))])

    # Next lets add implication  to all unsound invariants from first pass
    # Also add manually specified partialInvs
    unsound = [inv_ctr_pair[0] for inv_ctr_pair in p1_overfitted + p1_nonind]
    candidate_precedents = \
            [ ast_and(pSet) for pSet in nonempty(powerset(splitterPreds)) ]
    p2_invs = [
        AstBinExpr(precc, "==>", inv) for precc in candidate_precedents
        for inv in unsound
    ] + partialInvs

    p2_invs = \
        set([ x for x in p2_invs \
                if not conservative_tautology(expr_to_z3(x, AllIntTypeEnv())) ])

    # And look for any new sound invariants
    p2_overfitted, p2_nonind, p2_sound, violations = \
            tryAndVerify_impl(bbs, loop, p1_sound.union(set(partialInvs)), \
                              p2_invs, timeout)
    sound = p1_sound.union(p2_sound)

    return ((p1_overfitted, p2_overfitted), \
            (p1_nonind, p2_nonind), \
            sound, \
            violations)
Ejemplo n.º 2
0
def execute(env, bb, bbs, limit):
    q = [ (expr_to_z3(env_to_expr(env), AllIntTypeEnv()),
           bb ,
           SSAEnv(None, ""),
           [ ],
           [ ]) ]

    def bb_sp(bb, initial_ssa_env, precond):
      nd_path, final_env = nd_bb_path_to_ssa([bb], bbs, initial_ssa_env)
      sp = sp_nd_ssa_path(nd_path, bbs, precond, AllIntTypeEnv())
      return simplify(sp), final_env, nd_path

    while len(q) > 0:
      precond, bb, ssa_env, curp, cur_ssap = q.pop()
      #print "Running ", bb, " with pre: ", precond, "env:", ssa_env.replm()
      postcond, after_env, ssaed_bb = bb_sp(bb, ssa_env, precond)

      if (not satisfiable(postcond)):
        continue

      newp = curp + [ bb ]
      new_ssap = cur_ssap + ssaed_bb

      if (len(bbs[bb].successors) == 0 or len(curp) + 1 >= limit):
        yield postcond, after_env, newp, new_ssap, \
              extract_ssa_path_vars(new_ssap, model(postcond))
        continue

      for s in bbs[bb].successors:
        q.append((postcond, s, deepcopy(after_env), newp, new_ssap))
Ejemplo n.º 3
0
def instantiate(invs, traceVars, trace, mturkId):  #pylint: disable=unused-argument
    """ 
        Given a set of invariant templates inv, a set of variables traceVars
        and concrete values for these variables trace, return a set of concrete
        instances of the invariant templates, that hold for the given traces. A
        concrete instatnce of a template is an invariant with the same shape, with 
        variables and constants substituted in the appropriate places.

        Not currently in use.
    """
    res = []
    z3Invs = []
    templates = [(esprimaToBoogie(x[0], {}), x[1], x[2]) for x in invs]
    vals = map(lambda x: _to_dict(traceVars, x), trace)

    for (bInv, symConsts, symVars) in templates:
        for instInv in instantiateAndEval(bInv, vals, symVars, symConsts):
            instZ3Inv = expr_to_z3(instInv, AllIntTypeEnv())
            implied = False
            z3Inv = None

            for z3Inv in z3Invs:
                if implies(z3Inv, instZ3Inv):
                    implied = True
                    break

            if (implied):
                continue

            res.append(instInv)
            z3Invs.append(instZ3Inv)

    return map(boogieToEsprima, res)
Ejemplo n.º 4
0
def equiv(boogie1, boogie2):
    [p1,
     p2] = [expr_to_z3(pred, AllIntTypeEnv()) for pred in [boogie1, boogie2]]
    solv = getSolver()
    solv.add(Not(p1 == p2))
    res = solv.check()
    return res == unsat
Ejemplo n.º 5
0
def wp_stmt(stmt, pred, typeEnv):
    if (isinstance(stmt, AstLabel)):
        stmt = stmt.stmt

    if (isinstance(stmt, AstAssignment)):
        assignee = str(stmt.lhs)
        # Should already be SSA-ed
        assert(assignee not in expr_read(stmt.rhs))
        lhs = typeEnv[stmt.lhs](assignee)
        rhs = expr_to_z3(stmt.rhs, typeEnv)
        return z3.substitute(pred, (lhs, rhs))
    elif (isinstance(stmt, AstAssert)):
        return And(pred, expr_to_z3(stmt.expr, typeEnv))
    elif (isinstance(stmt, AstAssume)):
        return Implies(expr_to_z3(stmt.expr, typeEnv), pred)
    else:
        raise Exception("Cannot handle Boogie Statement: " + str(stmt))
Ejemplo n.º 6
0
def sp_stmt(stmt, pred, typeEnv):
    if (isinstance(stmt, AstLabel)):
        stmt = stmt.stmt

    if (isinstance(stmt, AstAssignment)):
        assignee = str(stmt.lhs)
        # Should already be SSA-ed
        assert(assignee not in expr_read(stmt.rhs) and \
              (assignee not in map(str, ids(pred))))
        lhs = typeEnv[stmt.lhs](assignee)
        rhs = expr_to_z3(stmt.rhs, typeEnv)
        return And(lhs == rhs, pred)
    elif (isinstance(stmt, AstAssert)):
        return And(pred, expr_to_z3(stmt.expr, typeEnv))
    elif (isinstance(stmt, AstAssume)):
        return And(pred, expr_to_z3(stmt.expr, typeEnv))
    else:
        raise Exception("Cannot handle Boogie Statement: " + str(stmt))
Ejemplo n.º 7
0
def simplifyInv(inv, mturkId):  #pylint: disable=unused-argument
    """ Given an invariant inv return its 'simplified' version. We
        treat that as the canonical version of an invariant. Simplification
        is performed by z3 """
    boogieInv = esprimaToBoogie(inv, {})
    noDivBoogie = divisionToMul(boogieInv)
    z3_inv = expr_to_z3(noDivBoogie, AllIntTypeEnv())
    print z3_inv, boogieInv
    simpl_z3_inv = simplify(z3_inv, arith_lhs=True)
    simpl_boogie_inv = z3_expr_to_boogie(simpl_z3_inv)
    return boogieToEsprima(simpl_boogie_inv)
Ejemplo n.º 8
0
        exit(1)

    additionalInvs = {}
    if args.additionalInvs:
        with open(args.additionalInvs) as f:
            r = csv.reader(f, delimiter=",")
            for row in r:
                if not row:
                    continue
                invs = []
                for invstr in invlist.split(";"):
                    if not len(invstr.strip()):
                        continue
                    try:
                        inv = parseExprAst(invstr)
                        if tautology(expr_to_z3(inv, AllIntTypeEnv())):
                            print "Dropping additional invariant (tautology): ", inv
                            continue
                    except RuntimeError:
                        # Some invariants are too large to parse
                        print "Dropping additional invariant (parse): ", inv
                        continue
                    except Unknown:
                        # Timeouts could be valid invariants
                        pass
                    invs.append(inv)
                additionalInvs[lvlName] = invs

    print "ADDITIONAL INVARIANTS LOADED FOR LVLS:", \
      ", ".join(additionalInvs.keys())
    print
Ejemplo n.º 9
0
def filterCandidateInvariants(bbs, preCond, postCond, cutPoints, timeout=None):
    assert (len(cutPoints) == 1)
    entryBB = bbEntry(bbs)

    cps = {bb: set(cutPoints[bb]) for bb in cutPoints}
    cps[entryBB] = [preCond]
    overfitted = {bb: set([]) for bb in cps}
    nonind = {bb: set([]) for bb in cps}

    # The separation in overfitted and nonind is well defined only in the
    # Single loop case. So for now only handle these. Can probably extend later

    aiTyEnv = AllIntTypeEnv()
    cpWorkQ = set([entryBB] + cps.keys())

    while (len(cpWorkQ) > 0):
        cp = cpWorkQ.pop()
        cp_inv = expr_to_z3(ast_and(cps[cp]), aiTyEnv)

        initial_path, intial_ssa_env = nd_bb_path_to_ssa([cp], bbs, SSAEnv())
        pathWorkQ = [(initial_path, intial_ssa_env, cp_inv)]

        # Pass 1: Widdle down candidate invariants at cutpoints iteratively
        while len(pathWorkQ) > 0:
            path, curFinalSSAEnv, sp = pathWorkQ.pop(0)

            nextBB, nextReplMaps = path[-1]
            processedStmts = []
            ssa_stmts = _ssa_stmts(bbs[nextBB].stmts, nextReplMaps)

            for s in ssa_stmts:
                if (isinstance(s, AstAssert)):
                    pass
                    # During the first pass we ignore safety violations. We just
                    # want to get an inductive invariant network
                elif (isinstance(s, AstAssume)):
                    try:
                        if (unsatisfiable(And(sp, expr_to_z3(s.expr, aiTyEnv)),
                                          timeout)):
                            break
                    except Unknown:
                        pass
                        # Conservatively assume path is possible on timeout
                processedStmts.append(s)
                new_sp = sp_stmt(s, sp, aiTyEnv)
                #print "SP: {", sp, "} ", s, " {", new_sp, "}"
                sp = new_sp

            if (len(processedStmts) != len(bbs[nextBB].stmts)):
                # Didn't make it to the end of the block - path must be unsat
                continue

            if (len(bbs[nextBB].successors) == 0):  # This is exit
                assert nextBB == bbExit(bbs)
                # During Pass 1 we don't check the postcondition is implied
            else:
                for succ in bbs[nextBB].successors:
                    if succ in cps:
                        # Check implication
                        start = initial_path[0][0]

                        candidate_invs = copy(cps[succ])
                        for candidate in candidate_invs:
                            candidateSSA = expr_to_z3(
                                replace(candidate, curFinalSSAEnv.replm()),
                                aiTyEnv)
                            try:
                                c = counterex(Implies(sp,
                                                      candidateSSA), timeout,
                                              "Candidate: " + str(candidate))
                            except Unknown:
                                c = {}  # On timeout conservatively assume fail

                            if (c != None):
                                v = Violation("inductiveness",
                                              path + [(succ, None)], [],
                                              Implies(sp, candidateSSA), c)

                                if (start == entryBB):
                                    overfitted[succ].add((candidate, v))
                                else:
                                    nonind[succ].add((candidate, v))

                                cps[succ].remove(candidate)
                        if (len(candidate_invs) != len(cps[succ])):
                            cpWorkQ.add(succ)
                    else:
                        assert succ not in path
                        # We should have cutpoints at every loop
                        succSSA, nextFinalSSAEnv = \
                                nd_bb_path_to_ssa([succ], bbs, SSAEnv(curFinalSSAEnv))
                        pathWorkQ.append((path + succSSA, nextFinalSSAEnv, sp))

    sound = cps

    # Pass 2: Check for safety violations
    violations = checkInvNetwork(bbs, preCond, postCond, sound, timeout)
    for v in violations:
        if (not v.isSafety()):
            print v
        assert (v.isSafety())  # sound should be an inductive network

    return (overfitted, nonind, sound, violations)
Ejemplo n.º 10
0
def checkInvNetwork(bbs, preCond, postCond, cutPoints, timeout=None):
    cps = copy(cutPoints)
    entryBB = bbEntry(bbs)
    cps[entryBB] = [preCond]
    aiTyEnv = AllIntTypeEnv()
    violations = []

    for cp in cps:
        initial_path, intial_ssa_env = nd_bb_path_to_ssa([cp], bbs, SSAEnv())
        workQ = [(initial_path, intial_ssa_env,
                  expr_to_z3(ast_and(cps[cp]), aiTyEnv))]
        while len(workQ) > 0:
            path, curFinalSSAEnv, sp = workQ.pop(0)

            nextBB, nextReplMaps = path[-1]
            processedStmts = []
            ssa_stmts = zip(_ssa_stmts(bbs[nextBB].stmts, nextReplMaps),
                            nextReplMaps)

            for (s, replM) in ssa_stmts:
                if (isinstance(s, AstAssert)):
                    try:
                        c = counterex(Implies(sp, expr_to_z3(s.expr, aiTyEnv)),
                                      timeout)
                    except Unknown:
                        c = {}  # On timeout conservatively assume fail
                    if (c != None):
                        # Current path can violate assertion
                        v = Violation("safety", path,
                                      processedStmts + [(s, replM)],
                                      Implies(sp, expr_to_z3(s.expr,
                                                             aiTyEnv)), c)
                        violations.append(v)
                        break
                elif (isinstance(s, AstAssume)):
                    try:
                        if (unsatisfiable(And(sp, expr_to_z3(s.expr, aiTyEnv)),
                                          timeout)):
                            break
                    except Unknown:
                        pass
                        # Conservatively assume path is possible on timeout
                processedStmts.append((s, replM))
                new_sp = sp_stmt(s, sp, aiTyEnv)
                #print "SP: {", sp, "} ", s, " {", new_sp, "}"
                sp = new_sp

            if (len(processedStmts) != len(bbs[nextBB].stmts)):
                # Didn't make it to the end of the block - path must be unsat or
                # violation found
                continue

            if (len(bbs[nextBB].successors) == 0):  # This is exit
                assert nextBB == bbExit(bbs)
                postSSA = expr_to_z3(replace(postCond, curFinalSSAEnv.replm()),
                                     aiTyEnv)
                try:
                    c = counterex(Implies(sp, postSSA), timeout)
                except Unknown:
                    c = {}  # On timeout conservatively assume fail
                if (c != None):
                    v = Violation("safety", path, processedStmts,
                                  Implies(sp, postSSA), c)
                    violations.append(v)
            else:
                for succ in bbs[nextBB].successors:
                    if succ in cps:
                        # Check implication
                        post = ast_and(cps[succ])
                        postSSA = replace(post, curFinalSSAEnv.replm())
                        postSSAZ3 = expr_to_z3(postSSA, aiTyEnv)
                        try:
                            c = counterex(Implies(sp, postSSAZ3), timeout)
                        except Unknown:
                            try:
                                # Sometimes its easier to check each post-invariant
                                # individually rather than all of them at once (similarly
                                # to the filter case). Try this if the implication of the
                                # conjunction of all of them fails
                                for p in cps[succ]:
                                    postSSA = replace(p,
                                                      curFinalSSAEnv.replm())
                                    postSSAZ3 = expr_to_z3(postSSA, aiTyEnv)
                                    c = counterex(Implies(sp, postSSAZ3),
                                                  timeout)
                                    # If any of them doesn't hold, neither does their conj
                                    if (c != None):
                                        break
                            except Unknown:
                                c = {}  # On timeout conservatively assume fail
                        if (c != None):
                            v = Violation("inductiveness",
                                          path + [(succ, None)], [],
                                          Implies(sp, postSSAZ3), c)
                            violations.append(v)
                    else:
                        assert succ not in path
                        # We should have cutpoints at every loop
                        succSSA, nextFinalSSAEnv = \
                                nd_bb_path_to_ssa([succ], bbs, SSAEnv(curFinalSSAEnv))
                        workQ.append((path + succSSA, nextFinalSSAEnv, sp))

    return violations
    args = p.parse_args();

    s = open_sqlite_db("../logs/" + args.ename + "/events.db")()
    lvlsetName, lvls = loadBoogieLvlSet(args.lvlset)

    otherInvs = { }
    if (args.additionalInvs):
      with open(args.additionalInvs) as f:
        r = csv.reader(f, delimiter=",");
        for row in r:
          (lvl, invs) = row
          bInvs = []
          for inv in [x for x in invs.split(";") if len(x.strip()) != 0]:
            try:
              bInv = parseExprAst(inv)
              if (tautology(expr_to_z3(bInv, AllIntTypeEnv()))):
                  continue
              bInvs.append(bInv)
            except RuntimeError:
              # Some invariants are just too large for parsing :(
              pass
            except Unknown:
              bInvs.append(bInv)

          otherInvs[lvl]=bInvs

    lvlStats = { lvlN: {
          "usersStarted": set(),\
          "nusersStarted": 0,\
          "usersFinished": set(),\
          "nusersFinished": 0,\
Ejemplo n.º 12
0
        origName = justEnd.split(lvl_name)[0]
        originalToSplitM[origName] = originalToSplitM.get(origName, []) +\
                                     [ lvl_name ]
        splitToOriginal[lvl_name] = origName

print "Checking splitter predicates non-ovrelapping"
for origName in originalToSplitM.keys():
    # For now we assume each split level has a single splitterPred
    preds = [
        unique(lvls[x]["splitterPreds"]) for x in originalToSplitM[origName]
    ]

    for i in xrange(0, len(preds)):
        for j in xrange(i + 1, len(preds)):
            if (not unsatisfiable(
                    expr_to_z3(bast.ast_and([preds[i], preds[j]]),
                               AllIntTypeEnv()))):
                print "Predicates ", preds[i], "and", preds[j], "from split of ", \
                       origName, "are not independent"

print "Checking conjunction of partial predicates is a solution"
for origName in originalToSplitM.keys():
    # For now we assume each split level has a single splitterPred
    preds = [lvls[x]["partialInv"] for x in originalToSplitM[origName]]
    if (len(preds) == 1):
        print "Skipping ", origName, "- only 1 split level (no other side of split)"
        continue
    conj = bast.ast_and(preds)
    lvl = lvls[originalToSplitM[origName][0]]
    try:
        (overfit, nonind, sound, violations) = verify(lvl, [conj])
        if (not len(violations) == 0):