static Program GetProgram(string filename) { var init = GetInputProgram(filename); if (Options.addInitialization) { ComputeandInitializeUninitializedLocals(init); } // Do some instrumentation for the input program if (Options.markAssumesAsSlic) { // Mark all assumes as "slic" var AddAnnotation = new Action <AssumeCmd>(ac => { ac.Attributes = new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes); }); init.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.Cmds.OfType <AssumeCmd>() .Iter(AddAnnotation))); } // Only keep assertions in assertProc procedures if (Options.assertProcs != null) { (new Instrumentations.PruneNonAssertProcs(Options.assertProcs)).Visit(init); } // Inline procedures supplied with {:inline} annotation cba.Driver.InlineProcedures(init); // Remove {:inline} impls init.RemoveTopLevelDeclarations(decl => (decl is Implementation) && (BoogieUtil.checkAttrExists("inline", decl.Attributes) || BoogieUtil.checkAttrExists("inline", (decl as Implementation).Proc.Attributes))); // Restrict entrypoints to those provided explicitly (overrides any other way to providing entryPoints) if (Options.entryPointProcs != null) { //only consider the user provided entry points in command line Options.useHarnessTag = false; Options.useProvidedEntryPoints = true; init.TopLevelDeclarations.OfType <NamedDeclaration>() .Iter(d => d.Attributes = BoogieUtil.removeAttr("entrypoint", d.Attributes)); } var matchesEntryPointExclude = new Func <string, bool>(s => { return(Options.entryPointExcludes.Any(t => new System.Text.RegularExpressions.Regex(t).IsMatch(s))); }); //when both entryPointProcs == null and entryPointExcludes == null, it should not add any entrypointProcs if (Options.entryPointProcs != null || Options.entryPointExcludes != null) { init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => d is Procedure || d is Implementation) .Where(d => Options.entryPointProcs == null || Options.entryPointProcs.Contains(d.Name)) .Where(d => (Options.entryPointExcludes == null || !matchesEntryPointExclude(d.Name))) .Iter(d => d.AddAttribute("entrypoint")); } // Add {:entrypoint} to procs with {:harness} if (Options.useHarnessTag) { foreach (var decl in init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => QKeyValue.FindBoolAttribute(d.Attributes, "harness"))) { decl.AddAttribute("entrypoint"); } } // inlining introduces havoc statements; lets just delete them (TODO: make inlining not introduce redundant havoc statements) //foreach (var impl in init.TopLevelDeclarations.OfType<Implementation>()) //{ // impl.Blocks.Iter(blk => // blk.Cmds.RemoveAll(cmd => cmd is HavocCmd)); //} ReplaceHavocsWithNonDet(init); //Instrument to create the harness harnessInstrumentation = new Instrumentations.HarnessInstrumentation(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.useProvidedEntryPoints); harnessInstrumentation.DoInstrument(); //resolve+typecheck wo bothering about modSets CommandLineOptions.Clo.DoModSetAnalysis = true; init = BoogieUtil.ReResolveInMem(init); CommandLineOptions.Clo.DoModSetAnalysis = false; // Update mod sets BoogieUtil.DoModSetAnalysis(init); if (Options.AddMapSelectNonNullAssumptions) { (new Instrumentations.AssertMapSelectsNonNull()).Visit(init); } BoogieUtil.pruneProcs(init, AvnAnnotations.CORRAL_MAIN_PROC); if (Options.deadCodeDetect) { // Tag branches as reachable var tup = InstrumentBranches.Run(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.UseAliasAnalysisForAngelicAssertions, false); init = tup.Item1; // TODO: inject this information into the program itself DeadCodeBranchesDependencyInfo = tup.Item2; } return(init); }
// Run Alias Analysis on a sequential Boogie program // and returned the pruned program public static PersistentProgram RunAliasAnalysis(PersistentProgram inp, bool pruneEP = true) { var newinp = inp; if (Options.unrollDepth > 0) { Stats.resume("unroll"); var unrp = new cba.LoopUnrollingPass(Options.unrollDepth); newinp = unrp.run(newinp); Stats.stop("unroll"); } var program = newinp.getProgram(); //AliasAnalysis.AliasAnalysis.dbg = true; //AliasAnalysis.AliasConstraintSolver.dbg = true; AliasAnalysis.AliasAnalysisResults res = null; if (Options.UseAliasAnalysisForAssertions) { // Do SSA program = SSA.Compute(program, PhiFunctionEncoding.Verifiable, new HashSet <string> { "int" }); if (Options.inlineDepth > 0) { Stats.resume("inlining"); Stats.resume("read.write"); program = BoogieUtil.ReResolveInMem(program); Stats.stop("read.write"); var op = CommandLineOptions.Clo.InlineDepth; CommandLineOptions.Clo.InlineDepth = Options.inlineDepth; cba.InliningPass.InlineToDepth(program); CommandLineOptions.Clo.InlineDepth = op; RemoveHavocs(program); Stats.stop("inlining"); } /* TODO: Is this needed? * Stats.resume("read.write"); * program = BoogieUtil.ReResolveInMem(program); * Stats.stop("read.write"); */ // Make sure that aliasing queries are on identifiers only var af = AliasAnalysis.SimplifyAliasingQueries.Simplify(program); Stats.resume("fixpoint"); res = AliasAnalysis.AliasAnalysis.DoAliasAnalysis(program); Stats.stop("fixpoint"); } else { // Make sure that aliasing queries are on identifiers only var af = AliasAnalysis.SimplifyAliasingQueries.Simplify(program); res = new AliasAnalysis.AliasAnalysisResults(); af.Iter(s => res.aliases.Add(s, true)); } var origProgram = inp.getProgram(); AliasAnalysis.PruneAliasingQueries.Prune(origProgram, res); if (pruneEP) { PruneRedundantEntryPoints(origProgram); } return(new PersistentProgram(origProgram, inp.mainProcName, inp.contextBound)); }
/** * Prune by removing implementations that are not called within depth k (k>=0) * When k < 0, only prune implementations that are never called * Leave corralExtraInint alone. */ private static Program pruneDeepProcs(Program origProgram, ref Dictionary <string, HashSet <string> > edges, string mainProcName, int k, HashSet <string> implNames) { if (mainProcName == null) { return(origProgram); } // delete all calls in CorralMain other than mainProcName mainProcName = sliceMainForProc(origProgram, mainProcName, implNames); var boundedDepth = (k >= 0); // do we have a bounded depth Program program = (new FixedDuplicator(false)).VisitProgram(origProgram); Procedure malloc = FindMalloc(program); var reachable = new HashSet <string>(); reachable.Add(mainProcName); var delta = new HashSet <string>(reachable); while (delta.Count != 0 && (!boundedDepth || k-- > 0)) { var nf = new HashSet <string>(); foreach (var n in delta) { if (edges.ContainsKey(n)) { nf.UnionWith(edges[n]); } } delta = nf.Difference(reachable); reachable.UnionWith(nf); } var allProcs = new HashSet <string>(edges.Keys); var toRemove = allProcs.Difference(reachable); var newDecls = new List <Declaration>(); foreach (var decl in program.TopLevelDeclarations) { //if (decl is Procedure && toRemove.Contains((decl as Procedure).Name)) continue; if (decl is Implementation) { var impl = decl as Implementation; if (toRemove.Contains(impl.Name) && !QKeyValue.FindBoolAttribute(impl.Attributes, AvUtil.AvnAnnotations.InitialializationProcAttr)) { // drop continue; } } newDecls.Add(decl); } program.TopLevelDeclarations = newDecls; if (approximationDepth >= 0) { program = BoogieUtil.ReResolveInMem(program, true); // instrument to add stubs AvHarnessInstrumentation.Driver.SetOptions(avHarnessInstrArgs.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); var hi = new AvHarnessInstrumentation.Instrumentations.HarnessInstrumentation(program, "", false); hi.DoInstrument(false); } return(program); }
public static Program InjectDualityProof(Program program, string DualityProofFile) { Program DualityProof; using (var st = new System.IO.StreamReader(DualityProofFile)) { var s = ParserHelper.Fill(st, new List <string>()); // replace %i by bound_var_i for (int i = 1; i <= 9; i++) { s = s.Replace(string.Format("%{0}", i), string.Format("pm_bv_{0}", i)); } var v = Parser.Parse(s, DualityProofFile, out DualityProof); if (v != 0) { throw new Exception("Failed to parse " + DualityProofFile); } } var implToContracts = new Dictionary <string, List <Expr> >(); foreach (var proc in DualityProof.TopLevelDeclarations.OfType <Procedure>()) { implToContracts.Add(proc.Name, new List <Expr>()); foreach (var ens in proc.Ensures) { implToContracts[proc.Name].AddRange(SimplifyExpr.GetExprConjunctions(ens.Condition)); } } var counter = 0; var GetExistentialConstant = new Func <Constant>(() => { var c = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "DualityProofConst" + (counter++), Microsoft.Boogie.Type.Bool), false); c.AddAttribute("existential"); return(c); }); var constsToAdd = new List <Declaration>(); foreach (var proc in program.TopLevelDeclarations.OfType <Procedure>()) { if (!implToContracts.ContainsKey(proc.Name)) { continue; } if (QKeyValue.FindBoolAttribute(proc.Attributes, "nohoudini")) { continue; } foreach (var expr in implToContracts[proc.Name]) { var c = GetExistentialConstant(); constsToAdd.Add(c); proc.Ensures.Add(new Ensures(false, Expr.Imp(Expr.Ident(c), expr))); } } program.AddTopLevelDeclarations(constsToAdd); return(BoogieUtil.ReResolveInMem(program)); }
private static Program PrepareQuery(IEnumerable <Implementation> loopImpls, Program program) { // Sometimes loops have multiple backedges, hence multiple recursive calls: merge them loopImpls.Iter(impl => mergeRecCalls(impl)); var dup = new FixedDuplicator(true); // Make copies of loopImpl procs var loopProcsCopy = new Dictionary <string, Procedure>(); loopImpls .Iter(impl => loopProcsCopy.Add(impl.Name, dup.VisitProcedure(impl.Proc))); loopProcsCopy.Values.Iter(proc => proc.Name += "_PassiveCopy"); // Make copies of the caller implementations var loopCallerImplCopy = new Dictionary <string, Implementation>(); var loopCallerProcCopy = new Dictionary <string, Procedure>(); loopImpls .Iter(impl => loopCallerImplCopy.Add(impl.Name, dup.VisitImplementation(loopCaller[impl.Name]))); loopImpls .Iter(impl => loopCallerProcCopy.Add(impl.Name, dup.VisitProcedure(loopCaller[impl.Name].Proc))); loopCallerImplCopy .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key); loopCallerProcCopy .Iter(kvp => kvp.Value.Name += "_EntryCopy_" + kvp.Key); loopCallerImplCopy .Iter(kvp => kvp.Value.Proc = loopCallerProcCopy[kvp.Key]); // Instrument callers foreach (var kvp in loopCallerImplCopy) { var impl = kvp.Value; var av = BoogieAstFactory.MkLocal("LoopBound_AssertVar", Microsoft.Boogie.Type.Bool); impl.LocVars.Add(av); // av := true var init = BoogieAstFactory.MkVarEqConst(av, true); var initCmds = new List <Cmd>(); initCmds.Add(init); initCmds.AddRange(impl.Blocks[0].Cmds); impl.Blocks[0].Cmds = initCmds; // av := false foreach (var blk in impl.Blocks) { var newCmds = new List <Cmd>(); for (int i = 0; i < blk.Cmds.Count; i++) { // disable assertions if (blk.Cmds[i] is AssertCmd && !BoogieUtil.isAssertTrue(blk.Cmds[i])) { newCmds.Add(new AssumeCmd(Token.NoToken, (blk.Cmds[i] as AssertCmd).Expr)); continue; } var cc = blk.Cmds[i] as CallCmd; if (cc != null && cc.callee == kvp.Key) { newCmds.Add(blk.Cmds[i]); newCmds.Add(BoogieAstFactory.MkVarEqConst(av, false)); } else if (cc != null && loopProcsCopy.ContainsKey(cc.callee)) { var ncc = new CallCmd(cc.tok, loopProcsCopy[cc.callee].Name, cc.Ins, cc.Outs, cc.Attributes, cc.IsAsync); ncc.Proc = loopProcsCopy[cc.callee]; newCmds.Add(ncc); } else { newCmds.Add(blk.Cmds[i]); } } blk.Cmds = newCmds; } // assert av impl.Blocks .Where(blk => blk.TransferCmd is ReturnCmd) .Iter(blk => blk.Cmds.Add(new AssertCmd(Token.NoToken, Expr.Ident(av)))); } // Prepare program var ret = new Program(); program.TopLevelDeclarations .Where(decl => !(decl is Implementation)) .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopProcsCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopCallerImplCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopCallerProcCopy.Values .Iter(decl => ret.AddTopLevelDeclaration(decl)); loopImpls .Iter(impl => ret.AddTopLevelDeclaration(impl)); loopCallerImplCopy.Values .Iter(impl => impl.AddAttribute("entrypoint")); // Store mapping: entrypoint -> loop loopImpls .Select(loop => Tuple.Create(loop, loopCallerImplCopy[loop.Name])) .Iter(tup => tup.Item2.AddAttribute("LB_Mapping", tup.Item1.Name)); ret = BoogieUtil.ReResolveInMem(ret); return(ret); }
static Program Process(Program program) { // Get rid of Synonyms RemoveTypeSynonyms.Remove(program); //BoogieUtil.PrintProgram(program, "tt.bpl"); program = BoogieUtil.ReResolveInMem(program, false); // Create "null" var nil = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "NULL", btype.Int), false); nil.AddAttribute("allocated"); // axiom NULL == 0; //var ax = new Axiom(Token.NoToken, Expr.Eq(Expr.Ident(nil), Expr.Literal(0))); program.AddTopLevelDeclaration(nil); //program.AddTopLevelDeclaration(ax); // add "allocator" to malloc program.TopLevelDeclarations.OfType <Procedure>() .Where(p => MallocNames.Contains(p.Name)) .Iter(p => p.AddAttribute("allocator")); // inline functions InlineFunctions(program); // Add attribute {:fpcondition} to assume cmds in charge of branching in function pointer dispatch procs var fpAt = new AnnotateFPDispatchProcVisitor(); fpAt.Run(program); // Add MustReach function calls to the begining of each procedure and upon returns if (detectDeadCode) { var ddc = new SimpleDeadcodeDectectionVisitor(); ddc.Run(program); } // if we don't check NULL, stop here if (!checkNULL && !checkUAF) { return(program); } if (checkUAF) { var iu = new InstrumentUAF(); iu.Instrument(program, nil); program.AddTopLevelDeclaration(new Axiom(Token.NoToken, Expr.Eq(Expr.Ident(nil), Expr.Literal(0)))); return(program); } // Remove literal constants var CE = new ConstantElimination(); CE.Run(program); // Convert 0 to NULL in the program ConvertToNull.Convert(program, nil); // Add NULL axiom here such that ConvertToNULL doesn't lead to dumb axiom var ax = new Axiom(Token.NoToken, Expr.Eq(Expr.Ident(nil), Expr.Literal(0))); program.AddTopLevelDeclaration(ax); // Add "assert !aliasQ(e, NULL)" for each expression M[e] appearing in the program InstrumentMemoryAccesses.Instrument(program, nil); // Put {:scalar} {:AllocatorVar} on $CurrAddr var alloc = program.TopLevelDeclarations.OfType <GlobalVariable>().Where(g => g.Name == allocVar) .FirstOrDefault(); if (alloc != null) { //alloc.AddAttribute("scalar"); alloc.AddAttribute(AvUtil.AvnAnnotations.AllocatorVarAttr); } else { Console.WriteLine("Warning: Global variable $CurrAddr not found"); } if (initMem) { InitMemory(program); } return(program); }
// Split on the postconditions of procedure "proc" // 1. only retain its postconditions; make everything else as assumes // 2. drop the implementation of the procedure // 3. convert calls to itself to calls to a fake procedure with assumed postconditions static Program SplitOnProcedure(Program program, string proc) { var dup = new FixedDuplicator(); program = dup.VisitProgram(program); program = BoogieUtil.ReResolveInMem(program, true); var toremove = new HashSet <Implementation>(); Implementation procimpl = null; foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { if (impl.Name == proc) { procimpl = impl; continue; } if (impl.Proc.Ensures.All(ens => ens.Free)) { continue; } var newens = new List <Ensures>(); impl.Proc.Ensures.Iter(ens => newens.Add(new Ensures(ens.tok, true, ens.Condition, ens.Comment))); impl.Proc.Ensures = newens; toremove.Add(impl); } program.RemoveTopLevelDeclarations(decl => decl is Implementation && toremove.Contains(decl)); if (procimpl != null) { // create copy var proccopy = dup.VisitProcedure(procimpl.Proc); proccopy.Name += "_dup"; // make assumes var newens = new List <Ensures>(); proccopy.Ensures.Iter(ens => newens.Add(new Ensures(ens.tok, true, ens.Condition, ens.Comment))); proccopy.Ensures = newens; foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>()) { foreach (var blk in impl.Blocks) { for (int i = 0; i < blk.Cmds.Count; i++) { var ccmd = blk.Cmds[i] as CallCmd; if (ccmd == null || ccmd.callee != procimpl.Name) { continue; } blk.Cmds[i] = new CallCmd(ccmd.tok, proccopy.Name, ccmd.Ins, ccmd.Outs, ccmd.Attributes); } } } program.AddTopLevelDeclaration(proccopy); } return(program); }