def convertCppFileForInvGen(cppFile, outFile): with NamedTemporaryFile(suffix=".cpp", delete=False) as processedF: # First strip #includes and add a int NONDET; badLinesRe = re.compile("(^#include.*$)|" + "int unknown[0-9]\(\);|" + "int __VERIFIER_nondet_int\(\);|" + "unsigned int __VERIFIER_nondet_uint\(\);|" + "_Bool __VERIFIER_nondet_bool\(\);") noNondetIntAssign = re.compile(" *= *__VERIFIER_nondet_int *\(\)") noNondetUIntAssign = re.compile(" *= *__VERIFIER_nondet_uint *\(\)") substStar = re.compile("while *\( *\* *\)") lines = open(cppFile).read().split("\n") lines = [l for l in lines if not badLinesRe.match(l)] lines = ["//Auto-generated by " + __file__ + " from " + cppFile ] + \ ["int NONDET;"] + lines lines = [noNondetIntAssign.sub("", l) for l in lines] lines = [noNondetUIntAssign.sub("", l) for l in lines] lines = [substStar.sub("while(NONDET)", l) for l in lines] processedF.write("\n".join(lines)) processedF.flush() error("De-included file in ", processedF.name) cpp_args = [ "cpp", "-D_Static_assert=assert", "-D_static_assert=assert", "-Dstatic_assert=assert", "-D__VERIFIER_assert=assert", "-D__VERIFIER_assume=assume", "-Dunknown1()=NONDET", "-Dunknown2()=NONDET", "-Dunknown3()=NONDET", "-Dunknown4()=NONDET", "-Dunknown5()=NONDET", "-DLARGE_INT=2147483647", "-D__VERIFIER_nondet_int()=NONDET", processedF.name, outFile ] call(cpp_args, stderr=STDOUT) error("CPP-ed file in ", outFile)
def runDaikon(varz: List[str], trace: List[List[BoogieVal]], nosuppress: bool=False) -> List[AstExpr]: with NamedTemporaryFile(suffix=".dtrace", delete=False, mode="w") as dtraceF: dtraceF.write(toDaikonTrace(varz,trace)); dtraceF.flush(); args = ["java", "daikon.Daikon"] if (nosuppress): # Lets disable all filters and enable all invariants args = args + \ flattenList([[ "--config_option", x + "=false" ] \ for x in filter_opts]) + \ flattenList([[ "--config_option", x + "=true" ] \ for x in inv_enable_opts]) args.append(dtraceF.name) raw = check_output(args).decode() call(["rm", basename(dtraceF.name)[:-len(".dtrace")]+".inv.gz"]) start = raw.index("LoopEntry:::") + len("LoopEntry:::") end = raw.index("Exiting Daikon.", start) invs = [x for x in [x.strip() for x in raw[start:end].split("\n")] if x != ""] # I don't understand how LinearTeranry invariants without justification are # displayed... Also getting lazy to fix the long line.. invs = [x for x in invs if "warning: too few samples for daikon.inv.ternary.threeScalar.LinearTernary invariant" not in x]; #pylint: disable=line-too-long invs = [x for x in invs if "(mod 0)" not in x]; parsable = [] for i in invs: try: parsable.append(parseExprAst(i)); except Exception: error("Failed parsing: ", i) return parsable
def runInvGen(cppFile, mainRoutine): with NamedTemporaryFile(suffix=".front.out", delete=False) as frontOut,\ NamedTemporaryFile(suffix=".invgen.out", delete=False) as invgenOut,\ NamedTemporaryFile(suffix=".pl", delete=False) as transitionsF: if isfile(INVGEN_PATH + "/frontend"): frontendName = "/frontend" else: frontendName = "/frontend.exe" if isfile(INVGEN_PATH + "/invgen"): invgenName = "/invgen" else: invgenName = "/invgen.exe" args = [ INVGEN_PATH + frontendName, "-main", mainRoutine, cppFile, "-o", transitionsF.name ] error("Frontend output in ", frontOut.name) try: check_call(args, stderr=STDOUT, stdout=frontOut) except CalledProcessError as e: raw = open(frontOut.name).read() outp = raw.split("\n") if outp[-2] == "Fatal error: exception ArmcStmt.NotImplemented(\"Mod\")": return ("NYI: Mod", [], outp) elif "Fatal error:" in raw and "Not implemented (unsigned int" in raw: return ("NYI: Unsigned Int Cast", [], outp) elif outp[-2] == "Fatal error: exception Failure(\"Push Negation failed! I am here!\")": #pylint: disable=line-too-long return ("Frontend Crash", [], outp) raise e error("Transitions file in ", transitionsF.name) args = [INVGEN_PATH + invgenName, transitionsF.name] error("Invgen output in ", invgenOut.name) try: raw = check_output(args, stderr=STDOUT) except CalledProcessError as e: outp = e.output.split("\n") if outp[-2] == "! 'All direct(loop free) path to error are unsat'": return ("InvGen Crash", [], outp) elif outp[-2] == "! pred2coeff('Bad Predicate')": return ("InvGen Crash", [], outp) raise e lines = raw.split("\n") while (lines[-1] == ''): lines.pop() solved = lines[-1].startswith("#Total Solving time:") invgenOut.write("\n".join(lines)) invgenOut.flush() if (solved): invRe = re.compile("^[^\[]*\[(?P<invs>[^\]]*)\]$") invariants = invRe.match(lines[-2]).groupdict()["invs"].split(",") else: invariants = [] return (solved, invariants, lines)
def loadLvlSet(lvlSetFile: str) -> Tuple[str, Dict[str, FlowgameLevel]]: # Small helper funct to make sure we didn't # accidentally give two levels the same name def assertUniqueKeys(kvs): keys = [x[0] for x in kvs] assert (len(set(keys)) == len(keys)) return dict(kvs) lvlSet = load(open(lvlSetFile, "r"), object_pairs_hook=assertUniqueKeys) lvlSetDir = dirname(abspath(realpath(lvlSetFile))) error("Loading level set " + lvlSet["name"] + " from " + lvlSetFile) lvls: Dict[str, FlowgameLevel] = OrderedDict() for t in lvlSet["levels"]: lvlName = t[0] lvlPath = t[1] for i in range(len(lvlPath)): lvlPath[i] = join(lvlSetDir, lvlPath[i]) error("Loading level: ", lvlPath[0]) fun = FlowgameLevel.load(lvlPath[0], lvlName) lvls[lvlName] = fun return (lvlSet["name"], lvls)
def loadBoogieLvlSet(lvlSetFile: str) -> Tuple[str, Dict[str, BoogieTraceLvl]]: # Small helper funct to make sure we didn't # accidentally give two levels the same name def assertUniqueKeys(kvs): keys = [x[0] for x in kvs] assert (len(set(keys)) == len(keys)) return dict(kvs) lvlSet = load(open(lvlSetFile, "r"), object_pairs_hook=assertUniqueKeys) lvlSetDir = dirname(abspath(realpath(lvlSetFile))) error("Loading level set " + lvlSet["name"] + " from " + lvlSetFile) lvls: Dict[str, BoogieTraceLvl] = OrderedDict() for t in lvlSet["levels"]: lvlName = t[0] lvlPath = t[1] for i in range(len(lvlPath)): lvlPath[i] = join(lvlSetDir, lvlPath[i]) error("Loading level: ", lvlPath[0]) lvl = loadBoogieFile(lvlPath[0]) lvl["path"] = lvlPath if (len(t) > 2): splitterPreds = [parseExprAst(exp) for exp in t[2]] splitterPred = ast_and(splitterPreds) remainderInv = parseExprAst(t[3]) lvl['data'][0] = [ row for row in lvl['data'][0] if eval_quick(splitterPred, {k: v for k, v in zip(lvl['variables'], row)}) ] if (len(lvl['data'][0]) == 0): error("SKIPPING : ", lvlName, " due to no filtered rows.") continue lvl['partialInv'] = remainderInv lvl['splitterPreds'] = splitterPreds lvls[lvlName] = lvl return (lvlSet["name"], lvls)
def runInvGen(cppFile, mainRoutine): with NamedTemporaryFile(suffix=".front.out", delete=False) as frontOut,\ NamedTemporaryFile(suffix=".invgen.out", delete=False) as invgenOut,\ NamedTemporaryFile(suffix=".pl", delete=False) as transitionsF: if isfile(INVGEN_PATH + "/frontend"): frontendName = "/frontend" else: frontendName = "/frontend.exe" if isfile(INVGEN_PATH + "/invgen"): invgenName = "/invgen" else: invgenName = "/invgen.exe" args = [ INVGEN_PATH + frontendName, "-main", mainRoutine, cppFile, "-o", transitionsF.name] error("Frontend output in ", frontOut.name) try: check_call(args, stderr=STDOUT, stdout=frontOut); except CalledProcessError,e: raw = open(frontOut.name).read(); outp = raw.split("\n") if outp[-2] == "Fatal error: exception ArmcStmt.NotImplemented(\"Mod\")": return ("NYI: Mod", [], outp) elif "Fatal error:" in raw and "Not implemented (unsigned int" in raw: return ("NYI: Unsigned Int Cast", [], outp) elif outp[-2] == "Fatal error: exception Failure(\"Push Negation failed! I am here!\")": #pylint: disable=line-too-long return ("Frontend Crash", [], outp) raise e error("Transitions file in ", transitionsF.name) args = [ INVGEN_PATH + invgenName, transitionsF.name] error("Invgen output in ", invgenOut.name) try: raw = check_output(args, stderr=STDOUT); except CalledProcessError,e: outp = e.output.split("\n"); if outp[-2] == "! 'All direct(loop free) path to error are unsat'": return ("InvGen Crash", [], outp); elif outp[-2] == "! pred2coeff('Bad Predicate')": return ("InvGen Crash", [], outp); raise e;
default=True, help='Print results as a csv table') p.add_argument('--time-limit', type=int, default=300, \ help='Time limit for ICE') p.add_argument('--waitEnter', action="store_true", \ default=False, help='Wait for user to perss Enter before continuing (great for debug)') args = p.parse_args() if args.waitEnter: eval(input("Press Enter to continue...")) lvlSetName, lvls = loadBoogieLvlSet(args.lvlset) res = {} conf = {} for lvlName, lvl in lvls.items(): boogieFile = lvl["path"][2] error("Running ", lvlName) res[lvlName] = runICE(boogieFile, args.time_limit) solved, loopHeaderLbl, loopInvs, rawOutput = res[lvlName] conf_status = "N/A" if (solved): error("z3 invs: ", len(loopInvs), loopInvs) try: t = Timer(args.time_limit, handler) t.start() #alarm(args.time_limit) # On lvl d-14 for example the invariants explode exponentially due to # inlining of lets. So add timeout. Seems to be the only level with # this problem
"nusersFinished": 0,\ "invs": set(),\ "ninvs": 0,\ "invariantsTried": set(),\ "nInvariantsTried": 0,\ "invariantsFound": set(),\ "nInvariantsFound": 0,\ "skipped": 0,\ "totalTime": timedelta(),\ } for lvlN in lvls } for e in s.query(Event).all(): typ, src, ename, time, p = e.type, e.src, e.experiment, e.time, e.payl() if ('lvlset' in p and p['lvlset'] != lvlsetName): error("Logs refer to levelset " + p['lvlset'] + " which is not loaded.") if ('lvlid' in p and p['lvlid'] not in lvls): error("Logs refer to level " + p['lvlid'] + \ " which is not found in current lvlset.") if ('lvlid' in p): lvl = lvls[p['lvlid']] lvlS = lvlStats[p['lvlid']] else: lvl = None lvlS = None if (typ == "FoundInvariant"): lvlS["invariantsFound"].add((p['raw'], p['canonical']))
help='Lvl-id in level set to try and verify"') p.add_argument('invs', type=str, nargs="+", help="Invariants to try") p.add_argument('--timeout', type=int, \ help="Optional z3 timeout", default=None) args = p.parse_args(); _, lvls = loadBoogieLvlSet(args.lvlset) lvl = lvls[args.lvlid] boogie_invs = set([]) for inv in args.invs: try: bInv = parseExprAst(inv); boogie_invs.add(bInv); except Exception: error("Failed parsing invariant " + inv); exit(-1); ((overfitted, overfitted_p2), (nonind, nonind_p2), sound, violations) =\ tryAndVerifyLvl(lvl, boogie_invs, set(), args.timeout) overfitted = set(overfitted).union(overfitted_p2) nonind = set(nonind).union(nonind_p2) print("Overfitted: ", overfitted) print("Nonind: ", nonind) print("Sound: ", sound) print("Violations: ", violations) print("Verified? ", len(violations) == 0)
stmt = bbs[s.pc.bb][s.pc.next_stmt] if not isinstance(stmt, AstAssume): return True v = eval_quick(stmt.expr, s.store) check(v, bool) return v feasible_states = filter(lambda x: lookahead_one_filter(bbs, x), states) return [choice(feasible_states)] filt_f = f else: error("Usage: unknown nond-mode: {}".format(args.nond_mode)) rand_f = lambda state, Id: randint(-1000, 1000) starting_state = State(PC(bbEntry(bbs), 0), starting_store, RUNNING) (active, inactive) = trace_n(bbs, starting_state, args.steps, rand_f, filt_f) def pp_state(st): return "[{},{}]: ".format(st.pc.bb, st.pc.next_stmt) + \ ",".join([k + "={}".format(v) for (k, v) in st.store.items()]) def pp_trace(t): return "->\n".join(map(pp_state, t)) print "Active({}):".format(len(active))
print "Level,Invariants,TranslatedTo,Solved,Confirmed" for lvlName, lvl in lvls.iteritems(): cppFile = lvl["path"][1] invgenCppFile = cppFile + ".invgen.preprocessed" if (not exists(invgenCppFile)): optionalManualModifiedFile = cppFile + ".invgen.manual.pretranslation" if (exists(optionalManualModifiedFile)): src = optionalManualModifiedFile else: src = cppFile convertCppFileForInvGen(src, invgenCppFile) error("Running ", lvlName) mainRoutine = "main" if lvlName != "i-cegar1" else "cegar1" res[lvlName] = runInvGen(invgenCppFile, mainRoutine) solved, loopInvs, rawOutput = res[lvlName] conf_status = "n/a" if (solved == True): error("z3 invs: ", len(loopInvs), loopInvs) boogieInvs = map(parseInvGenInvariant, loopInvs) bbs = lvl["program"] loop = lvl["loop"] try: ((overfitted, overfitted2), (nonind, nonind2), sound, violations) =\ tryAndVerifyLvl(lvl, set(boogieInvs), set(), args.time_limit, \