// Verify that the trace is a valid counterexample (i.e., it returns an assertion-failure counterexample // upon verification. // Returns a program that consists of a single implementation with a single basic // block that contains the trace. public bool verifyTrace(out Program newProg) { // Currently, this only works for intraprocedural traces Debug.Assert(acex.calleeCounterexamples.Count == 0); HashSet <string> calledProcs; Implementation traceImpl = getImplementation(out calledProcs); newProg = new Program(); // The set of called procedures should only be ones // that do not have an implementation foreach (Declaration decl in prog.TopLevelDeclarations) { if (decl is GlobalVariable) { newProg.AddTopLevelDeclaration(decl); } else if (decl is Procedure) { Procedure tmp = decl as Procedure; if (calledProcs.Contains(tmp.Name)) { newProg.AddTopLevelDeclaration(decl); } else if (tmp.Name == impl.Name) { Procedure pex = new Procedure(Token.NoToken, tmp.Name + "_cex", tmp.TypeParameters, tmp.InParams, tmp.OutParams, tmp.Requires, tmp.Modifies, tmp.Ensures, tmp.Attributes); newProg.AddTopLevelDeclaration(pex); } } else if (decl is Implementation) { Implementation tmp = decl as Implementation; Debug.Assert(!calledProcs.Contains(tmp.Name)); } else { // Just add the other guys (axioms, functions, etc.) newProg.AddTopLevelDeclaration(decl); } } newProg.AddTopLevelDeclaration(traceImpl); newProg = BoogieUtil.ReResolve(newProg, "cex.bpl"); Program newProgCopy = BoogieUtil.ReadAndResolve("cex.bpl"); // (We need to create a copy because Boogie.Verify changes the input program) var errors = new List <BoogieErrorTrace>(); var ret = BoogieVerify.Verify(newProgCopy, out errors); if (ret != BoogieVerify.ReturnStatus.NOK) { return(false); } return(true); }
static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("usage: SmackInst.exe infile.bpl outfile.bpl [options]"); return; } if (args.Any(a => a == "/break")) { System.Diagnostics.Debugger.Launch(); } if (args.Any(a => a == "/initMem")) { initMem = true; } // initialize Boogie CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; // Read the input file var program = BoogieUtil.ReadAndResolve(args[0]); // Process it program = Process(program); // write the output BoogieUtil.PrintProgram(program, args[1]); }
//TODO: collect some stats about the instrumentation, mb some debugging output?? private static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("usage: PropInst.exe propertyFile.avp boogieInputFile.bpl boogieOutputFile.bpl"); return; } if (args.Any(s => s == "/break")) { System.Diagnostics.Debugger.Launch(); } // initialize Boogie CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; // read the boogie program that is to be instrumented var boogieProgram = BoogieUtil.ReadAndResolve(args[1], false); // parse the property file var propLines = File.ReadLines(args[0]); string globalDeclarations; List <Rule> rules; CreateRulesFromProperty(propLines, out globalDeclarations, out rules); // GlobalDeclarations: add the global declarations from the property to the Boogie program Program dummyProg; Parser.Parse(globalDeclarations, "dummy.bpl", out dummyProg); boogieProgram.AddTopLevelDeclarations(dummyProg.TopLevelDeclarations); //resolve the program with the new declarations which may include funcs and procs with bodies boogieProgram.Resolve(); // CmdRule: find insertions sites (Commands), insert code there InstrumentCmdRule.Instrument(boogieProgram, rules.OfType <CmdRule>()); // InsertAtBeginningRule: find insertion sites (Procedures), insert code there InstrumentProcedureRule.Instrument(boogieProgram, rules.OfType <InsertAtBeginningRule>()); // make functions with {:mkUniqueFn} unique (new MkUniqueFnVisitor(boogieProgram)).Visit(boogieProgram); //augment the CorralExtraInit procedure (perform this after Matching/instrumentation) AugmentCorralExtraInit(boogieProgram); string outputFile = args[2]; BoogieUtil.PrintProgram(boogieProgram, outputFile); Stats.printStats(); }
static void Main(string[] args) { if (args.Length != 1) { Console.WriteLine("Usage: SplitRMT.exe file.bpl"); return; } // Initialize CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; var program = BoogieUtil.ReadAndResolve(args[0]); // check input foreach (var proc in program.TopLevelDeclarations.OfType <Procedure>()) { if (proc.Requires.Any(req => !req.Free)) { Console.WriteLine("Error: non-free requires not yet supported"); return; } } var eplist = program.TopLevelDeclarations.OfType <Implementation>() .Where(impl => QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint") || QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "entrypoint")); if (eplist.Count() != 1) { Console.WriteLine("Error: Unique entrypoint not found"); return; } var main = eplist.First(); Console.WriteLine("Entrypoint: {0}", main.Name); // entrypoint + all assumes MarkAllAssumes(program, args[0]); // split on asserted postconditions var cnt = Split(program, args[0]); Console.WriteLine("Produced {0} file(s) after splitting", cnt); }
static void Main(string[] args) { if (args.Length != 2) { Console.WriteLine("BctMemInst.exe input.bpl output.bpl [args]"); return; } CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; CommandLineOptions.Clo.DoModSetAnalysis = true; var input = BoogieUtil.ReadAndResolve(args[0]); var output = Process(input); if (output != null) { BoogieUtil.PrintProgram(output, args[1]); } }
//TODO: collect some stats about the instrumentation, mb some debugging output?? private static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("usage: PropInst.exe propertyFile.avp boogieInputFile.bpl boogieOutputFile.bpl"); return; } // initialize Boogie CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; // read the boogie program that is to be instrumented var boogieProgram = BoogieUtil.ReadAndResolve(args[1], false); // parse the property file var propLines = File.ReadLines(args[0]); string globalDeclarations; List <Rule> rules; CreateRulesFromProperty(propLines, out globalDeclarations, out rules); // GlobalDeclarations: add the global declarations from the property to the Boogie program Program dummyProg; Parser.Parse(globalDeclarations, "dummy.bpl", out dummyProg); boogieProgram.AddTopLevelDeclarations(dummyProg.TopLevelDeclarations); // CmdRule: find insertions sites (Commands), insert code there InstrumentCmdRule.Instrument(boogieProgram, rules.OfType <CmdRule>()); // InsertAtBeginningRule: find insertion sites (Procedures), insert code there InstrumentProcedureRule.Instrument(boogieProgram, rules.OfType <InsertAtBeginningRule>()); string outputFile = args[2]; BoogieUtil.PrintProgram(boogieProgram, outputFile); Stats.printStats(); }
//TODO: collect some stats about the instrumentation, mb some debugging output?? private static void Main(string[] args) { if (args.Length < 3) { Console.WriteLine("usage: PropInst.exe propertyFile.avp boogieInputFile.bpl boogieOutputFile.bpl [options]"); Console.WriteLine("\t /pruneMethodsWithFilePathPrefix:<absolutePath> Prune implementations whose path has this prefix"); Console.WriteLine("\t /removeAssertsIfNoCallWithPrefix:<prefixString> Cleanup asserts if no methods prefixed with <prefixString> (e.g. ProbeFor) are present in the module"); return; } if (args.Any(s => s == "/break")) { System.Diagnostics.Debugger.Launch(); } var pruneFilePaths = new HashSet <string>(); args .Where(s => s.StartsWith("/pruneMethodsWithFilePathPrefix:")) .Iter(s => pruneFilePaths.Add(s.Substring("/pruneMethodsWithFilePathPrefix:".Length))); string cleanupPrefixString = null; var removeAssertConditions = args.Where(x => x.StartsWith("/removeAssertsIfNoCallWithPrefix:")); if (removeAssertConditions.Count() == 1) { cleanupPrefixString = removeAssertConditions.First().Substring("/removeAssertsIfNoCallWithPrefix:".Length); } else if (removeAssertConditions.Count() > 1) { Console.WriteLine("Expecting exactly one \"/removeAssertsIfNoCallWithPrefix:\" flag"); return; } // initialize Boogie CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; // read the boogie program that is to be instrumented var boogieProgram = BoogieUtil.ReadAndResolve(args[1], false); // parse the property file var propLines = File.ReadLines(args[0]); string globalDeclarations; List <Rule> rules; CreateRulesFromProperty(propLines, out globalDeclarations, out rules); // GlobalDeclarations: add the global declarations from the property to the Boogie program Program dummyProg; Parser.Parse(globalDeclarations, "dummy.bpl", out dummyProg); boogieProgram.AddTopLevelDeclarations(dummyProg.TopLevelDeclarations); //resolve the program with the new declarations which may include funcs and procs with bodies boogieProgram.Resolve(); // CmdRule: find insertions sites (Commands), insert code there InstrumentCmdRule.Instrument(boogieProgram, rules.OfType <CmdRule>()); // InsertAtBeginningRule: find insertion sites (Procedures), insert code there InstrumentProcedureRule.Instrument(boogieProgram, rules.OfType <InsertAtBeginningRule>()); // make functions with {:mkUniqueFn} unique (new MkUniqueFnVisitor(boogieProgram)).Visit(boogieProgram); //augment the CorralExtraInit procedure (perform this after Matching/instrumentation) AugmentCorralExtraInit(boogieProgram); // prune methods that match PruneFilePaths if (pruneFilePaths.Count() > 0) { PruneMethodsWithPaths(boogieProgram, pruneFilePaths); } // cleanup asserts if no method with prefix is present if (cleanupPrefixString != null) { PerformCleanupIfNoCallWithPrefix(boogieProgram, cleanupPrefixString); } string outputFile = args[2]; BoogieUtil.PrintProgram(boogieProgram, outputFile); Stats.printStats(); }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: RunEE file.bpl options"); return; } CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; var program = BoogieUtil.ReadAndResolve(args[0]); if (program.TopLevelDeclarations.OfType <Implementation>().Count() != 1) { Console.WriteLine("Error: input program must have exactly one implementation"); } var flags = ""; for (int i = 1; i < args.Length; i++) { if (args[i] == "/break") { System.Diagnostics.Debugger.Launch(); continue; } flags += args[i] + " "; } ExplainError.STATUS status; Dictionary <string, string> complexObj; HashSet <List <Expr> > preDisjuncts; List <Tuple <string, int, string> > eeSlicedSourceLines; var explain = ExplainError.Toplevel.Go(program.TopLevelDeclarations.OfType <Implementation>().First(), program, ExplainErrorTimeout, ExplainErrorFilters, flags, null, new HashSet <AssumeCmd>(), out status, out complexObj, out preDisjuncts, out eeSlicedSourceLines); if (status == ExplainError.STATUS.SUCCESS && explain.Count > 0) { var aliasingExplanation = ""; for (int i = 0; i < explain.Count; i++) { if (i == 0) { aliasingExplanation += "\n "; } else { aliasingExplanation += "\nor "; } aliasingExplanation += explain[i].TrimEnd(' ', '\t').Replace(' ', '_').Replace("\t", "_and_"); } if (complexObj.Any()) { aliasingExplanation += "\nwhere"; foreach (var tup in complexObj) { var str = string.Format(" {0} = {1}", tup.Value, tup.Key); aliasingExplanation += "^" + str.Replace(' ', '_'); } } Console.WriteLine("EE returned SUCCESS"); Console.WriteLine("{0}", aliasingExplanation); } else { Console.WriteLine("EE returned status: {0}", status); } }
public static ReturnStatus Verify(Program program, bool needErrorTraces, out List <BoogieErrorTrace> allErrors, out List <string> timedOut, bool isCBA = false) { ReturnStatus ret = ReturnStatus.OK; allErrors = new List <BoogieErrorTrace>(); timedOut = new List <string>(); Debug.Assert(program != null); // Make a copy of the input program var duper = new FixedDuplicator(true); var origProg = new Dictionary <string, Implementation>(); if (needErrorTraces) { foreach (var decl in program.TopLevelDeclarations) { if (decl is Implementation) { var origImpl = duper.VisitImplementation(decl as Implementation); origProg.Add(origImpl.Name, origImpl); } } } if (removeAsserts) { RemoveAsserts(program); } // Set options options.Set(); // save RB var rb = CommandLineOptions.Clo.RecursionBound; if (BoogieVerify.irreducibleLoopUnroll >= 0) { CommandLineOptions.Clo.RecursionBound = BoogieVerify.irreducibleLoopUnroll; } // Do loop extraction var extractionInfo = program.ExtractLoops(); // restore RB CommandLineOptions.Clo.RecursionBound = rb; // set bounds if (options.extraRecBound != null) { options.extraRecBound.Iter(tup => { var impl = BoogieUtil.findProcedureImpl(program.TopLevelDeclarations, tup.Key); if (impl != null) { impl.AddAttribute(BoogieVerify.ExtraRecBoundAttr, Expr.Literal(tup.Value)); } }); } #region Save program to disk if (shuffleProgram) { BoogieUtil.PrintProgram(program, "last_query.bpl"); program = BoogieUtil.ReadAndResolve("last_query.bpl"); } if (options.printProg) { Debug.Assert(options.progFileName != null, "Invalid options"); BoogieUtil.PrintProgram(program, options.progFileName); } #endregion var origBlocks = new Dictionary <string, Tuple <Block, Implementation> >(); // ---------- Infer invariants -------------------------------------------------------- // Abstract interpretation -> Always use (at least) intervals, if not specified otherwise (e.g. with the "/noinfer" switch) //Microsoft.Boogie.AbstractInterpretation.AbstractInterpretation.RunAbstractInterpretation(program); //// ---------- Verify ---------------------------------------------------------------- var mains = new List <Implementation>( program.TopLevelDeclarations .OfType <Implementation>() .Where(impl => QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"))); VC.VCGen vcgen = null; try { Debug.Assert(CommandLineOptions.Clo.StratifiedInlining > 0); if (options.newStratifiedInlining) { if (options.newStratifiedInliningAlgo.ToLower() == "duality") { Microsoft.Boogie.SMTLib.Factory.UseInterpolation = true; } vcgen = new CoreLib.StratifiedInlining(program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, null); } else // vcgen = new VC.StratifiedVCGen(options.CallTree != null, options.CallTree, options.procsToSkip, options.extraRecBound, program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, new List<Checker>()); if (!useDuality || !isCBA || !needErrorTraces || options.StratifiedInlining > 1 || mains.Count > 1) { vcgen = new VC.StratifiedVCGen(options.CallTree != null, options.CallTree, program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, new List <Checker>()); } else { CommandLineOptions.Clo.FixedPointMode = CommandLineOptions.FixedPointInferenceMode.Corral; CommandLineOptions.Clo.FixedPointEngine = "duality"; vcgen = new Microsoft.Boogie.FixedpointVC(program, CommandLineOptions.Clo.ProverLogFilePath, CommandLineOptions.Clo.ProverLogFileAppend, new List <Checker>(), options.extraRecBound); } } catch (ProverException e) { Log.WriteLine(Log.Error, "ProverException: {0}", e.Message); return(ReturnStatus.OK); } if (!mains.Any()) { throw new InternalError("No entrypoint found"); } if (mains.Count > 1) { Console.WriteLine("Verifying {0} impls", mains.Count); } foreach (var impl in mains) { if (PrintImplsBeingVerified) { Log.WriteLine(Log.Verbose, "Verifying implementation " + impl.Name); } List <Counterexample> errors; VC.VCGen.Outcome outcome; try { var start = DateTime.Now; outcome = vcgen.VerifyImplementation(impl, out errors); var end = DateTime.Now; TimeSpan elapsed = end - start; Log.WriteLine(Log.Debug, string.Format(" [{0} s] ", elapsed.TotalSeconds)); verificationTime += elapsed; if (recordTempTime) { tempTime += elapsed; } } catch (VC.VCGenException e) { throw new InternalError("VCGenException: " + e.Message); //errors = null; //outcome = VC.VCGen.Outcome.Inconclusive; } catch (UnexpectedProverOutputException upo) { throw new InternalError("Unexpected prover output: " + upo.Message); //errors = null; //outcome = VC.VCGen.Outcome.Inconclusive; } switch (outcome) { case VC.VCGen.Outcome.Correct: break; case VC.VCGen.Outcome.Errors: break; case VC.VCGen.Outcome.ReachedBound: ret = ReturnStatus.ReachedBound; break; case VC.VCGen.Outcome.Inconclusive: throw new InternalError("z3 says inconclusive"); case VC.VCGen.Outcome.OutOfMemory: // wipe out any counterexamples timedOut.Add(impl.Name); errors = new List <Counterexample>(); break; case VC.VCGen.Outcome.OutOfResource: case VC.VCGen.Outcome.TimedOut: // wipe out any counterexamples timedOut.Add(impl.Name); errors = new List <Counterexample>(); break; default: throw new InternalError("z3 unknown response"); } Log.WriteLine(Log.Debug, outcome.ToString()); Log.WriteLine(Log.Debug, (errors == null ? 0 : errors.Count) + " counterexamples."); if (errors != null) { ret = ReturnStatus.NOK; } // Print model if (errors != null && errors.Count > 0 && errors[0].Model != null && CommandLineOptions.Clo.ModelViewFile != null) { var model = errors[0].Model; var cnt = 0; model.States.Iter(st => { if (st.Name.StartsWith("corral")) { st.ChangeName(st.Name + "_" + cnt.ToString()); cnt++; } }); using (var wr = new StreamWriter(CommandLineOptions.Clo.ModelViewFile, false)) { model.Write(wr); } } if (errors != null && needErrorTraces) { for (int i = 0; i < errors.Count; i++) { //errors[i].Print(1, Console.Out); // Map the trace across loop extraction if (vcgen is VC.VCGen) { errors[i] = (vcgen as VC.VCGen).extractLoopTrace(errors[i], impl.Name, program, extractionInfo); } if (errors[i] is AssertCounterexample) { // Special treatment for assert counterexamples for CBA: Reconstruct // trace in the input program. ReconstructImperativeTrace(errors[i], impl.Name, origProg); allErrors.Add(new BoogieAssertErrorTrace(errors[i] as AssertCounterexample, origProg[impl.Name], program)); } else { allErrors.Add(new BoogieErrorTrace(errors[i], origProg[impl.Name], program)); } } } } //PutBackAsserts(program); if (vcgen is StratifiedVCGen) { CallTreeSize = (vcgen as StratifiedVCGen).numInlined; vcSize = (vcgen as StratifiedVCGen).vcsize; if (options.CallTree != null) { options.CallTree = VC.StratifiedVCGen.callTree; VC.StratifiedVCGen.callTree = null; } } else if (vcgen is CoreLib.StratifiedInlining) { procsHitRecBound = (vcgen as CoreLib.StratifiedInlining).procsHitRecBound; CallTreeSize = (vcgen as CoreLib.StratifiedInlining).stats.numInlined; vcSize = (vcgen as CoreLib.StratifiedInlining).stats.vcSize; if (options.CallTree != null) { options.CallTree = (vcgen as CoreLib.StratifiedInlining).GetCallTree(); } } else { CallTreeSize = 0; } vcgen.Close(); CommandLineOptions.Clo.TheProverFactory.Close(); return(ret); }
static void Main(string[] args) { if (args.Length < 1) { Console.WriteLine("Usage: HoudiniLite.exe file.bpl [options]"); return; } var file = args[0]; var boogieArgs = ""; var check = false; var dual = false; for (int i = 1; i < args.Length; i++) { if (args[i] == "/break") { System.Diagnostics.Debugger.Launch(); continue; } if (args[i] == "/check") { check = true; continue; } if (args[i] == "/dual") { dual = true; continue; } boogieArgs += args[i] + " "; } Initalize(boogieArgs); if (dual) { HoudiniInlining.DualHoudini = true; } var sw = new Stopwatch(); sw.Start(); var assignment = new HashSet <string>(); try { assignment = HoudiniInlining.RunHoudini(BoogieUtil.ReadAndResolve(file), true); } catch (DualHoudiniFail e) { Console.WriteLine("DualHoudini failed to prove anything useful: {0}", e.Message); } sw.Stop(); Console.WriteLine("HoudiniLite took: {0} seconds", sw.Elapsed.TotalSeconds.ToString("F2")); HoudiniStats.Print(); Console.WriteLine("Num true = {0}", assignment.Count); if (CommandLineOptions.Clo.PrintAssignment) { Console.WriteLine("True assignment: {0}", assignment.Concat(" ")); } if (check) { sw.Restart(); CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; CommandLineOptions.Clo.UseSubsumption = CommandLineOptions.SubsumptionOption.Never; CommandLineOptions.Clo.ContractInfer = true; BoogieUtil.InitializeBoogie(boogieArgs); var actual = RunBoogieHoudini(BoogieUtil.ReadAndResolve(file)); sw.Stop(); Console.WriteLine("Houdini took: {0} seconds", sw.Elapsed.TotalSeconds.ToString("F2")); if (!assignment.Equals(actual)) { Console.WriteLine("Constants proved by us but not houdini: {0}", assignment.Difference(actual).Concat(" ")); Console.WriteLine("Constants proved by houdini but not us: {0}", actual.Difference(assignment).Concat(" ")); } } }
public static void ReadFiles(IEnumerable <string> files, HashSet <string> keepPatterns) { foreach (var f in files) { Program program; try { program = BoogieUtil.ReadAndResolve(f); } catch (cba.Util.InvalidProg) { continue; } CheckRMT(program); fileToKeepConstants.Add(f, new HashSet <string>()); // Add annotations foreach (var p in keepPatterns) { var re = new Regex(p); program.TopLevelDeclarations.OfType <Constant>() .Where(c => QKeyValue.FindBoolAttribute(c.Attributes, "existential") && re.IsMatch(c.Name)) .Iter(c => { c.AddAttribute(Driver.MustKeepAttr); fileToKeepConstants[f].Add(c.Name); }); } // Prune, according to annotations DropConstants(program, new HashSet <string>( program.TopLevelDeclarations.OfType <Constant>() .Where(c => QKeyValue.FindBoolAttribute(c.Attributes, Driver.DropAttr)) .Select(c => c.Name))); var allconstants = new Dictionary <string, Constant>(); program.TopLevelDeclarations.OfType <Constant>() .Where(c => QKeyValue.FindBoolAttribute(c.Attributes, "existential")) .Iter(c => allconstants.Add(c.Name, c)); // Normalize expressions if (!SimplifyExpr.SimplifyToCNF) { program.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Proc.Ensures.Iter(ens => SimplifyExpr.SimplifyEnsures(ens, allconstants))); } else { var constants = new HashSet <string>(allconstants.Keys); program.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Proc.Ensures = SimplifyExpr.SimplifyEnsures(impl.Proc.Ensures, allconstants)); allconstants.Where(tup => !constants.Contains(tup.Key)) .Iter(tup => program.AddTopLevelDeclaration(tup.Value)); } // Remove constants that don't hold -- optimization HashSet <string> consts = new HashSet <string>(allconstants.Keys); HashSet <string> assignment; int perf = 0; if (Driver.InitBound > 0) { perf = Driver.InitBound; } var ret = PruneAndRun(new PersistentProgram(program), consts, out assignment, ref perf); if (ret != BoogieVerify.ReturnStatus.OK) { Console.WriteLine("Warning: Program {0} doesn't have an initial inductive proof", f); continue; } // anything not in assignment can be dropped DropConstants(program, consts.Difference(assignment)); consts.Difference(assignment).Iter(s => allconstants.Remove(s)); fileToKeepConstants[f].IntersectWith(assignment); Console.WriteLine("File {0} defines {1} constants ({2} dropped)", f, assignment.Count, consts.Count - assignment.Count); // initial perf fileToPerf.Add(f, perf); // create template map foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { foreach (var ens in impl.Proc.Ensures.Where(e => !e.Free)) { string constantName = null; Expr expr = null; var isloop = QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "LoopProcedure"); var match = Microsoft.Boogie.Houdini.Houdini.GetCandidateWithoutConstant( ens.Condition, allconstants.Keys, out constantName, out expr); if (!match) { continue; } if (fileToKeepConstants[f].Contains(constantName)) { continue; } var priorTemplateId = QKeyValue.FindIntAttribute(ens.Attributes, "template", -1); var temp = SimplifyExpr.ExprToTemplateGeneral(expr); if (strToTemplate.ContainsKey(temp)) { // template for it exists addTemplate(strToTemplate[temp], f, constantName, Tuple.Create(isloop, expr)); } else { // create new template strToTemplate.Add(temp, TemplateCounterStart + strToTemplate.Count); addTemplate(strToTemplate[temp], f, constantName, Tuple.Create(isloop, expr)); } if (priorTemplateId != -1) { priorFullyInstantiatedTemplates.Add(strToTemplate[temp]); } } } // stash the program fileToProg.Add(f, new PersistentProgram(program)); } templateToStr = new Dictionary <int, string>(); strToTemplate.Iter(tup => templateToStr.Add(tup.Value, tup.Key)); Console.WriteLine("Found {0} templates", templateMap.Count); if (dbg) { foreach (var tup in templateMap) { Console.WriteLine("Template {0} :: {1}", tup.Key, templateToStr[tup.Key]); foreach (var tup2 in tup.Value) { Console.WriteLine(" File {0}", tup2.Key); tup2.Value.Iter(c => Console.WriteLine(" Candidate {0}", c)); } } } }
static void Main(string[] args) { Console.CancelKeyPress += Console_CancelKeyPress; if (args.Length < 1) { Console.WriteLine("ProofMin file(s).bpl [options]"); return; } var boogieArgs = ""; var once = false; var printcontracts = false; var keepPatterns = new HashSet <string>(); var filePatterns = new HashSet <string>(); for (int i = 0; i < args.Length; i++) { if (!args[i].StartsWith("/") && args[i].EndsWith(".bpl")) { filePatterns.Add(args[i]); continue; } if (args[i].StartsWith("/files:")) { filePatterns.UnionWith( System.IO.File.ReadAllLines(args[i].Substring("/files:".Length))); continue; } if (args[i] == "/break") { System.Diagnostics.Debugger.Launch(); continue; } if (args[i] == "/once") { once = true; continue; } if (args[i] == "/noSI") { Minimize.useSI = false; Minimize.usePerf = 2.0; continue; } if (args[i] == "/dbg") { dbg = true; Minimize.dbg = true; continue; } if (args[i] == "/printAssignment") { printcontracts = true; continue; } if (args[i].StartsWith("/keep:")) { keepPatterns.Add(args[i].Substring("/keep:".Length)); continue; } if (args[i].StartsWith("/initBound:")) { InitBound = Int32.Parse(args[i].Substring("/initBound:".Length)); continue; } if (args[i] == "/perf") { Minimize.usePerf = 2.0; continue; } if (args[i] == "/cnf") { SimplifyExpr.SimplifyToCNF = true; continue; } if (args[i].StartsWith("/perf:")) { Minimize.usePerf = double.Parse(args[i].Substring("/perf:".Length)); continue; } boogieArgs += args[i] + " "; } // Initialize Boogie boogieArgs += " /typeEncoding:m /weakArrayTheory /errorLimit:1 "; Initalize(boogieArgs); // Get the input files var files = new HashSet <string>(); foreach (var fp in filePatterns) { var fname = System.IO.Path.GetFileName(fp); var dirname = System.IO.Path.GetDirectoryName(fp); if (dirname == "") { dirname = "."; } files.UnionWith(System.IO.Directory.GetFiles(dirname, fname)); } if (files.Count == 0) { Console.WriteLine("No files given"); return; } Console.WriteLine("Found {0} files", files.Count); if (once) { Debug.Assert(files.Count() == 1); RunOnce(new PersistentProgram(BoogieUtil.ReadAndResolve(files.First(), true)), printcontracts); return; } Minimize.sw.Start(); Minimize.ReadFiles(files, keepPatterns); Dictionary <int, int> templateToPerfDelta = new Dictionary <int, int>(); HashSet <int> min = new HashSet <int>(); var dropped = new HashSet <int>(); var ApplyTemplatesDone = false; do { do { Dictionary <int, int> t2d; var min2 = Minimize.FindMin(dropped, out t2d); // dropped var templates = new HashSet <int>(Minimize.templateToStr.Keys); dropped = templates.Difference(min2); // merge perf foreach (var tup in t2d) { if (!templateToPerfDelta.ContainsKey(tup.Key)) { templateToPerfDelta.Add(tup.Key, tup.Value); } else { templateToPerfDelta[tup.Key] += tup.Value; } } Console.WriteLine("Obtained minimal templates, at size {0}", min2.Count); if (min.SetEquals(min2)) { Console.WriteLine("Reached fixpoint; we're done"); break; } min = min2; Console.WriteLine("Contemplating re-running with broken down templates"); var rerun = false; Minimize.candidateToCost = new Dictionary <int, int>(); var newTemplates = new HashSet <int>(); min2.Iter(t => { var b = Minimize.PruneDisjuncts(t, ref newTemplates); rerun |= b; }); if (!rerun) { Console.WriteLine("Nothing to break; we're done"); break; } dropped.ExceptWith(newTemplates); Console.WriteLine("Rerunning Minimization"); } while (true); if (ApplyTemplatesDone) { break; } ApplyTemplatesDone = true; // compute common set of globals var rr = Minimize.ApplyTemplates(min.Difference(Minimize.priorFullyInstantiatedTemplates)); if (!rr) { break; } } while (true); foreach (var c in min) { Console.WriteLine("Template to origin info for {0} : {1}", c, Minimize.templateToStr[c]); if (!Minimize.templateToOriginExpr.ContainsKey(c) || Minimize.templateToOriginExpr[c].Count == 0) { continue; } foreach (var tup in Minimize.templateToOriginExpr[c]) { Console.WriteLine(" {0}{1}", tup.Item1 ? "{:loop} " : "", tup.Item2.ToString()); } } foreach (var c in min) { var gen = Minimize.templateToStr[c]; string ret = gen; if (Minimize.templateToOriginExpr.ContainsKey(c) && Minimize.templateToOriginExpr[c].Count != 0) { var isloop = Minimize.templateToOriginExpr[c].All(tup => tup.Item1); var exprs = Minimize.templateToOriginExpr[c].Select(tup => SimplifyExpr.ExprToTemplateSpecific(tup.Item2, isloop)); ret = exprs.First(); ret = exprs.All(s => s == ret) ? ret : gen; ret = isloop ? string.Format("{{:loop}} {0}", ret) : ret; } Console.WriteLine("Additional contract required: {0}", ret); } foreach (var tup in templateToPerfDelta) { if (tup.Value <= 2) { continue; } Console.WriteLine("Contract to pref: {0} {1}", tup.Value, Minimize.templateToStr[tup.Key]); } Console.WriteLine("Cache hits on calls to PruneAndRun: {0} / {1}", Minimize.CacheHit, Minimize.IterCnt); }
static void Main(string[] args) { if (args.Length < 2) { Console.WriteLine("usage: SmackInst.exe infile.bpl outfile.bpl [options]"); return; } if (args.Any(a => a == "/break")) { System.Diagnostics.Debugger.Launch(); } if (args.Any(a => a == "/initMem")) { initMem = true; } if (args.Any(a => a == "/replaceRoot")) { replaceRoot = true; } args.Where(a => a.StartsWith("/oldRoot:")) .Iter(a => oldRoot = a.Substring("/oldRoot:".Length)); args.Where(a => a.StartsWith("/newRoot:")) .Iter(a => newRoot = a.Substring("/newRoot:".Length)); if (args.Any(a => a == "/count")) { count = true; } if (args.Any(a => a == "/onlyCount")) { onlyCount = true; } if (args.Any(a => a == "/checkNULL")) { checkNULL = true; } if (args.Any(a => a == "/checkUAF")) { checkUAF = true; } if (args.Any(a => a == "/printCallGraph")) { printCallGraph = true; } if (args.Any(a => a == "/detectDeadCode")) { detectDeadCode = true; } if (args.Any(a => a == "/checkMemorySafety")) { checkMemSafety = true; } if (args.Any(a => a == "/visualizeHeap")) { visualizeHeap = true; } // initialize Boogie CommandLineOptions.Install(new CommandLineOptions()); CommandLineOptions.Clo.PrintInstrumented = true; CommandLineOptions.Clo.DoModSetAnalysis = true; // Read the input file var program = BoogieUtil.ReadAndResolve(args[0], false); // SMACK does not add globals to modify clauses //BoogieUtil.DoModSetAnalysis(program); if (checkMemSafety) { Procedure checkProc = program.TopLevelDeclarations.OfType <Procedure>().Where(x => x.Name == "__SMACK_check_memory_safety").FirstOrDefault(); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { if (impl.Name == "__SMACK_check_memory_safety") { continue; } if (impl.Name.StartsWith("__SMACK_static_init")) { continue; } foreach (var block in impl.Blocks) { //var block = impl.Blocks.FirstOrDefault(); var newCmds = new List <Cmd>(); foreach (var cmd in block.cmds) { if (cmd is AssignCmd) { var asnCmd = cmd as AssignCmd; var rhs = asnCmd.Rhss.FirstOrDefault(); if (rhs is NAryExpr) { var fcExpr = rhs as NAryExpr; if (fcExpr.Fun.FunctionName.StartsWith("$load") || fcExpr.Fun.FunctionName.StartsWith("$store")) { char[] delim = { '.' }; var type = fcExpr.Fun.FunctionName.Split(delim)[1]; var size = 0; if (type == "ref") { size = 8; } else { size = Int32.Parse(type.Substring(1)) / 8; } var ptr = fcExpr.Args[1]; //Console.WriteLine(ptr.ToString()); var sizeExpr = Expr.Ident(size.ToString(), btype.Int); var paramList = new List <Expr>(); paramList.Add(ptr); paramList.Add(sizeExpr); var callCmd = new CallCmd(Token.NoToken, "__SMACK_check_memory_safety", paramList, new List <IdentifierExpr>()); newCmds.Add(callCmd); } } } if (cmd is CallCmd) { var callCmd = cmd as CallCmd; if (callCmd.callee.StartsWith("corral_fix_context_")) { continue; } } if (cmd is AssertCmd) { continue; } newCmds.Add(cmd); } block.cmds = newCmds; } } BoogieUtil.PrintProgram(program, args[1]); return; } if (visualizeHeap) { Procedure printProc = program.TopLevelDeclarations.OfType <Procedure>().Where(x => x.Name == "boogie_si_record_ref").FirstOrDefault(); foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { if (impl.Name.StartsWith("__SMACK_static_init")) { continue; } foreach (var block in impl.Blocks) { //var block = impl.Blocks.FirstOrDefault(); var newCmds = new List <Cmd>(); foreach (var cmd in block.cmds) { if (cmd is AssignCmd) { var asnCmd = cmd as AssignCmd; var rhs = asnCmd.Rhss.FirstOrDefault(); if (rhs is NAryExpr) { var fcExpr = rhs as NAryExpr; if (fcExpr.Fun.FunctionName.StartsWith("$load")) { var region = fcExpr.Args[0]; if (region.ToString().Equals("$M.0")) { var val = asnCmd.Lhss.FirstOrDefault().AsExpr; var ptr = fcExpr.Args[1]; List <Expr> paramList = new List <Expr>(); paramList.Add(val); var callCmd = new CallCmd(Token.NoToken, "boogie_si_record_ref", paramList, new List <IdentifierExpr>()); List <Object> attrib = new List <Object>(); attrib.Add(val.ToString()); callCmd.Attributes = new QKeyValue(Token.NoToken, "cexpr", attrib, callCmd.Attributes); newCmds.Add(cmd); newCmds.Add(callCmd); continue; } } if (fcExpr.Fun.FunctionName.StartsWith("$store")) { var region = fcExpr.Args[0]; if (region.ToString().Equals("$M.0")) { var val = fcExpr.Args[2]; List <Expr> paramList = new List <Expr>(); paramList.Add(val); var callCmd = new CallCmd(Token.NoToken, "boogie_si_record_ref", paramList, new List <IdentifierExpr>()); List <Object> attrib = new List <Object>(); attrib.Add(val.ToString()); callCmd.Attributes = new QKeyValue(Token.NoToken, "cexpr", attrib, callCmd.Attributes); newCmds.Add(callCmd); } } } } newCmds.Add(cmd); } block.cmds = newCmds; } } BoogieUtil.PrintProgram(program, args[1]); return; } if (printCallGraph) { PrintCallGraphToDot(program, "i386_immediate", "callgraph.dot"); return; } // Preprocess program: count lines + replace Root program = preProcess(program, count || onlyCount, oldRoot, newRoot); if (onlyCount) { return; } // Process it program = Process(program); // write the output BoogieUtil.PrintProgram(program, args[1]); }