예제 #1
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)));
            }

            // 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);
        }
예제 #2
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.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));
        }
예제 #3
0
        /**
         * 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);
        }
예제 #4
0
        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));
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        // 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);
        }