Esempio n. 1
0
        // 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);
        }
Esempio n. 2
0
        // Prune away non-candidates, verify using the rest
        static BoogieVerify.ReturnStatus PruneAndRun(PersistentProgram inp, HashSet <string> candidates, out HashSet <string> assignment, ref int inlined)
        {
            var program = inp.getProgram();

            program.Typecheck();

            program = BoogieUtil.ReResolve(program);

            // Remove non-candidates
            CoreLib.HoudiniInlining.InstrumentHoudiniAssignment(program, candidates, true);
            program.RemoveTopLevelDeclarations(decl => (decl is Constant) && QKeyValue.FindBoolAttribute(decl.Attributes, "existential") &&
                                               !candidates.Contains((decl as Constant).Name));

            //BoogieUtil.PrintProgram(program, "hi_query" + IterCnt + ".bpl");

            // Run Houdini
            var ot = CommandLineOptions.Clo.ProverKillTime;

            CommandLineOptions.Clo.ProverKillTime = HoudiniTimeout;
            assignment = CoreLib.HoudiniInlining.RunHoudini(program, true);
            CommandLineOptions.Clo.ProverKillTime = ot;
            //Console.WriteLine("  >> Contracts: {0}", assignment.Count);

            // Read the program again, add contracts
            program = inp.getProgram();
            program.Typecheck();

            CoreLib.HoudiniInlining.InstrumentHoudiniAssignment(program, assignment);
            //BoogieUtil.PrintProgram(program, "si_query" + IterCnt + ".bpl");

            // Run SI
            var err = new List <BoogieErrorTrace>();

            // Set bound
            BoogieVerify.options.maxInlinedBound = 0;
            if (inlined != 0)
            {
                BoogieVerify.options.maxInlinedBound = PerfMetric(inlined);
            }

            var rstatus = BoogieVerify.Verify(program, out err, true);

            //Console.WriteLine(string.Format("  >> Procedures Inlined: {0}", BoogieVerify.CallTreeSize));
            //Console.WriteLine(string.Format("Boogie verification time: {0} s", BoogieVerify.verificationTime.TotalSeconds.ToString("F2")));

            inlined = BoogieVerify.CallTreeSize + 1;
            BoogieVerify.options.CallTree = new HashSet <string>();
            BoogieVerify.CallTreeSize     = 0;
            BoogieVerify.verificationTime = TimeSpan.Zero;

            return(rstatus);
        }
Esempio n. 3
0
        static Program Process(Program program)
        {
            // Get rid of Synonyms
            RemoveTypeSynonyms.Remove(program);
            //BoogieUtil.PrintProgram(program, "tt.bpl");
            program = BoogieUtil.ReResolve(program);

            // add "allocator" to malloc
            program.TopLevelDeclarations.OfType <Procedure>()
            .Where(p => MallocNames.Contains(p.Name))
            .Iter(p => p.AddAttribute("allocator"));

            // 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)));

            // Convert 0 to NULL in the program
            ConvertToNull.Convert(program, nil);

            program.AddTopLevelDeclaration(nil);
            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);
        }
Esempio n. 4
0
        static IEnumerable <Function> DoInference(Program program, InferenceMode mode, string annotatedFileName, string expandedFileName)
        {
            var tmpFileName = "og__tmp_di.bpl";

            if (mode == InferenceMode.SEQUENTIAL)
            {
                // remove yields
                program.TopLevelDeclarations.OfType <Implementation>()
                .Iter(impl => impl.Blocks
                      .Iter(blk => blk.Cmds = new List <Cmd>(blk.Cmds.Filter(c => !(c is YieldCmd)))));
            }

            // Run OG
            if (dbg)
            {
                Console.WriteLine("Running OG: {0}", expandedFileName);
            }

            LinearTypeChecker linearTypechecker;
            CivlTypeChecker   moverTypeChecker;
            var oc = ExecutionEngine.ResolveAndTypecheck(program, annotatedFileName, out linearTypechecker, out moverTypeChecker);

            if (oc != PipelineOutcome.ResolvedAndTypeChecked)
            {
                throw new Exception(string.Format("{0} type checking errors detected in {1}", linearTypechecker.errorCount, annotatedFileName));
            }

            Concurrency.Transform(linearTypechecker, moverTypeChecker);
            var eraser = new LinearEraser();

            eraser.VisitProgram(program);

            //var stats = new PipelineStatistics();
            //ExecutionEngine.EliminateDeadVariablesAndInline(program);
            //var ret = ExecutionEngine.InferAndVerify(program, stats);
            //ExecutionEngine.printer.WriteTrailer(stats);
            //return;

            program = BoogieUtil.ReResolve(program, dbg ? expandedFileName : tmpFileName);

            // Run Abs
            if (dbg)
            {
                Console.WriteLine("Running abs houdini on {0}", expandedFileName);
            }

            ExecutionEngine.EliminateDeadVariables(program);
            ExecutionEngine.Inline(program);

            var domain = Microsoft.Boogie.Houdini.AbstractDomainFactory.GetInstance(absDomain);

            var abs     = new Microsoft.Boogie.Houdini.AbsHoudini(program, domain);
            var outcome = abs.ComputeSummaries();

            if (outcome.outcome != VC.ConditionGeneration.Outcome.Correct)
            {
                Console.WriteLine("Some assert failed while running AbsHoudini, aborting");
                outcome.errors.Iter(error => og.PrintError(error));
            }

            return(abs.GetAssignment());
        }
Esempio n. 5
0
        static void Main(string[] args)
        {
            con = new Context();

            string
                inFileName           = null,
                unrolledFileName     = null,
                tidRewrittenFileName = null,
                expandedFileName     = null,
                annotatedFileName    = null,
                splitFileName        = null,
                yieldedFileName      = null,
                instantiatedFileName = null,
                finalFileName        = null,
                mhpFileName          = null,
                hmifFileName         = null;

            dbg = false;

            inFileName = parseCommandLine(args);

            string[] parts = inFileName.Split('.');
            if (parts.Count() == 1)
            {
                unrolledFileName     = inFileName + "_unrolled";
                hmifFileName         = inFileName + "_hmif";
                expandedFileName     = inFileName + "_expanded";
                tidRewrittenFileName = inFileName + "_tidRewritten";
                annotatedFileName    = inFileName + "_annotated";
                splitFileName        = inFileName + "_split";
                yieldedFileName      = inFileName + "_yielded";
                finalFileName        = inFileName + "_final";
                mhpFileName          = inFileName + "_mhp";
                instantiatedFileName = inFileName + "_inst";
            }
            else
            {
                string name = parts[0];
                unrolledFileName     = name + "_unrolled";
                hmifFileName         = name + "_hmif";
                expandedFileName     = name + "_expanded";
                annotatedFileName    = name + "_annotated";
                splitFileName        = name + "_split";
                yieldedFileName      = name + "_yielded";
                finalFileName        = name + "_final";
                mhpFileName          = name + "_mhp";
                instantiatedFileName = name + "_inst";
                tidRewrittenFileName = name + "_tidRewritten";
                for (int i = 1; i < parts.Count(); ++i)
                {
                    unrolledFileName     += "." + parts[i];
                    hmifFileName         += "." + parts[i];
                    expandedFileName     += "." + parts[i];
                    annotatedFileName    += "." + parts[i];
                    splitFileName        += "." + parts[i];
                    yieldedFileName      += "." + parts[i];
                    finalFileName        += "." + parts[i];
                    tidRewrittenFileName += "." + parts[i];
                    mhpFileName          += "." + parts[i];
                    instantiatedFileName += "." + parts[i];
                }
            }

            var tmpFileName = "og__tmp.bpl";

            ExecutionEngine.printer = new ConsolePrinter();
            //CommanLineOptions will control how boogie parses the program and gives us the IR
            CommandLineOptions.Install(new CommandLineOptions());
            CommandLineOptions.Clo.Parse(new string[] { });
            CommandLineOptions.Clo.PrintInstrumented         = true;
            CommandLineOptions.Clo.StratifiedInliningVerbose = 2;
            CommandLineOptions.Clo.UseArrayTheory            = true;
            CommandLineOptions.Clo.TypeEncodingMethod        = CommandLineOptions.TypeEncoding.Monomorphic;

            Program program;

            program = BoogieUtil.ReadAndOnlyResolve(inFileName);

            // TODO: assert that no procedure can be called in both sync and async mode!


            // Find entrypoint and initialize con
            var entry = program.TopLevelDeclarations.OfType <Procedure>()
                        .Where(proc => QKeyValue.FindBoolAttribute(proc.Attributes, "entrypoint"))
                        .FirstOrDefault();

            if (entry == null)
            {
                Console.WriteLine("Warning: No entrypoint given");
                con.entryFunc = null;
            }
            else
            {
                con.entryFunc = entry.Name;
            }

            // Remove unreachable procedures
            BoogieUtil.pruneProcs(program, con.entryFunc);

            // Extract loops
            if (extractLoops)
            {
                program.ExtractLoops();
            }

            BoogieUtil.DoModSetAnalysis(program);

            if (pruneAsserts)
            {
                program = og.GuardAsserts(program);
            }

            if (injectYields)
            {
                program = og.InsertYields(program);
            }

            if (instantiateTemplates)
            {
                var inst = new TemplateInstantiator(program);
                inst.Instantiate(program);
                program = BoogieUtil.ReResolve(program, dbg ? instantiatedFileName : tmpFileName);
            }

            var sp   = new SplitThreads(con, dbg);
            var hmif = new HowManyInstanceFinder(con, dbg);

            var split = new Converter <Program, Program>(sp.split);
            var findHowManyInstances = new Converter <Program, Program>(hmif.Compute);

            if (entry != null && splitThreads)
            {
                if (dbg)
                {
                    Console.WriteLine("Splitting procedures on thread entry: {0}", splitFileName);
                }

                program = split(program);
                program = BoogieUtil.ReResolve(program, dbg ? hmifFileName : tmpFileName);

                program = findHowManyInstances(program);
                program = BoogieUtil.ReResolve(program, dbg ? splitFileName : tmpFileName);
            }

            // Get rid of corral_yield
            program = og.RemoveCorralYield(program, con.yieldProc);


            var yieldedProgram = new ProgTransformation.PersistentProgram(program);

            if (dbg)
            {
                Console.WriteLine("Instrumenting: {0}", annotatedFileName);
            }

            if (!noTid)
            {
                program = og.InstrumentTid(program);
            }

            program = og.InstrumentAtomicBlocks(program);

            if (instrumentPermissions)
            {
                program = og.InstrumentPermissions(program);
            }

            program = BoogieUtil.ReResolve(program, dbg ? annotatedFileName : tmpFileName);

            CommandLineOptions.Clo.ContractInfer     = true;
            CommandLineOptions.Clo.AbstractHoudini   = absDomain;
            CommandLineOptions.Clo.UseProverEvaluate = true;
            CommandLineOptions.Clo.ModelViewFile     = "z3model";
            Microsoft.Boogie.Houdini.AbstractDomainFactory.Initialize(program);

            // First, do sequential
            var answer = DoInference(program, InferenceMode.SEQUENTIAL, annotatedFileName, expandedFileName);

            program = BoogieUtil.ReadAndOnlyResolve(dbg ? annotatedFileName : tmpFileName);

            // prune "true" functions
            var progFuncs = new Dictionary <string, Function>();

            program.TopLevelDeclarations.OfType <Function>()
            .Iter(f => progFuncs.Add(f.Name, f));

            var truefuncs = new List <Function>();

            foreach (var f in answer)
            {
                if (f.Body is LiteralExpr && (f.Body as LiteralExpr).IsTrue)
                {
                    truefuncs.Add(f);
                    var actualf = progFuncs[f.Name];
                    actualf.Attributes = BoogieUtil.removeAttr("existential", actualf.Attributes);
                    actualf.Body       = Expr.True;
                }
            }
            Console.WriteLine("Sequential check pruned away {0} functions, {1} remain", truefuncs.Count, answer.Count() - truefuncs.Count);

            // now do concurrent
            answer = DoInference(program, InferenceMode.CONCURRENT, annotatedFileName, expandedFileName);
            answer = answer.Concat(truefuncs);

            var provedAsserts = new Dictionary <string, bool>();

            answer.Where(func => QKeyValue.FindBoolAttribute(func.Attributes, "assertGuard"))
            .Iter(func => {
                var le = func.Body as LiteralExpr;
                System.Diagnostics.Debug.Assert(le != null);
                provedAsserts.Add(func.Name, le.IsFalse);
            });

            // remove injected existential functions
            answer = answer.Where(func => !QKeyValue.FindBoolAttribute(func.Attributes, "chignore") &&
                                  !QKeyValue.FindBoolAttribute(func.Attributes, "assertGuard"));

            if (printAssignment)
            {
                using (var tt = new TokenTextWriter(Console.Out))
                    answer.ToList().Iter(func => func.Emit(tt, 0));
            }


            if (dbg)
            {
                Console.WriteLine("Injecting invariants back into the original program: {0}", finalFileName);
            }

            program = yieldedProgram.getProgram();

            // remove existential functions
            program.RemoveTopLevelDeclarations(decl => (decl is Function) && QKeyValue.FindBoolAttribute((decl as Function).Attributes, "existential"));
            program.AddTopLevelDeclarations(answer);

            program = og.PruneProvedAsserts(program, f => provedAsserts[f]);

            // Remove ensures and requires
            program = og.RemoveRequiresAndEnsures(program);
            // Remove tid func
            program = og.RemoveThreadIdFunc(program);
            using (Microsoft.Boogie.TokenTextWriter writer = new Microsoft.Boogie.TokenTextWriter(finalFileName))
                program.Emit(writer);
        }
Esempio n. 6
0
        // 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.ReResolve(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");
                }

                Stats.resume("read.write");
                program = BoogieUtil.ReResolve(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));
        }
Esempio n. 7
0
        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)));
            }

            // 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)));

            // 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));
            }

            //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.ReResolve(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);
        }