Example #1
0
def tryAndVerifyWithSplitterPreds(
        fun: Function,
        old_sound_invs: Set[AstExpr],
        boogie_invs: Set[AstExpr],
        splitterPreds: List[AstExpr],
        partialInvs: List[AstExpr],
        timeout: Optional[int] = None) -> TryAndVerifyResult:
    """ 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_nonind 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
    """
    initial_sound = old_sound_invs.union(partialInvs)
    boogieTypeEnv = fun.getTypeEnv()
    z3TypeEnv = boogieToZ3TypeEnv(boogieTypeEnv)

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

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

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

    # And look for any new sound invariants
    p2_overfitted, p2_nonind, p2_sound, violations = \
            tryAndVerify_impl(fun, 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)
Example #2
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
Example #3
0
def simplifyInv(inv: EsprimaNode, typeEnv: JSONTypeEnv, mturkId: MturkIdT) -> EsprimaNode: #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 """
    boogieEnv = jsonToTypeEnv(typeEnv)
    z3Env = boogieToZ3TypeEnv(boogieEnv)

    boogieInv = esprimaToBoogie(inv, {})
    noDivBoogie = divisionToMul(boogieInv)
    z3_inv = expr_to_z3(noDivBoogie, z3Env)
    simpl_z3_inv = ccast(simplify(z3_inv, arith_lhs=True), z3.ExprRef)
    simpl_boogie_inv = z3_expr_to_boogie(simpl_z3_inv)
    return boogieToEsprima(simpl_boogie_inv)
Example #4
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:", \
Example #5
0
  if (endsWithNumP.match(lvl_name)):
    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 list(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 range(0, len(preds)):
    for j in range(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 list(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):