Beispiel #1
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            p.Typecheck();

            p.TopLevelDeclarations.OfType <Procedure>().Iter(proc => procsWithoutBody.Add(proc.Name));
            p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => procsWithoutBody.Remove(impl.Name));

            // remove malloc
            //procsWithoutBody.RemoveWhere(str => str.Contains("malloc"));

            // Make sure that procs without a body don't modify globals
            foreach (var proc in p.TopLevelDeclarations.OfType <Procedure>().Where(proc => procsWithoutBody.Contains(proc.Name)))
            {
                if (proc.Modifies.Count > 0 && !BoogieUtil.checkAttrExists("allocator", proc.Attributes))
                {
                    throw new InvalidInput("Produce Bug Witness: Procedure " + proc.Name + " modifies globals");
                }
            }

            // Add the boogie_si_record_int procedure
            var inpVarInt  = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Int), true);
            var inpVarBool = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Bool), true);

            var reProcInt = new Procedure(Token.NoToken, recordProcNameInt, new List <TypeVariable>(), new List <Variable> {
                inpVarInt
            }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>());
            var reProcBool = new Procedure(Token.NoToken, recordProcNameBool, new List <TypeVariable>(), new List <Variable> {
                inpVarBool
            }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>());

            // Add procedures for initialization of local variables
            foreach (var impl in p.TopLevelDeclarations.OfType <Implementation>())
            {
                var ncmds = new List <Cmd>();
                foreach (var loc in (impl.LocVars.Concat(impl.OutParams)))
                {
                    var cc = new CallCmd(Token.NoToken, GetInitLocalsProc(loc.TypedIdent.Type).Name, new List <Expr>(), new List <IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(loc) }));
                    cc.Attributes = new QKeyValue(Token.NoToken, RestrictToTrace.ConcretizeConstantNameAttr, new List <object> {
                        LocalVarInitValueAttr
                    }, cc.Attributes);
                    cc.Proc = GetInitLocalsProc(loc.TypedIdent.Type);
                    ncmds.Add(cc);
                }
                ncmds.AddRange(impl.Blocks[0].Cmds);
                impl.Blocks[0].Cmds = ncmds;
            }
            typeToInitLocalsProc.Values.Iter(pr => procsWithoutBody.Add(pr.Name));
            typeToInitLocalsProc.Values.Iter(pr => p.AddTopLevelDeclaration(pr));

            // save the current program
            var fd         = new FixedDuplicator(true);
            var modInpProg = fd.VisitProgram(p);

            // Instrument to record stuff
            p.TopLevelDeclarations.OfType <Implementation>().Iter(impl =>
                                                                  impl.Blocks.Iter(b => instrument(b)));

            // Name clash if this assert fails
            Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameInt) == null);
            Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameBool) == null);
            foreach (var rp in typeToRecordProc.Values)
            {
                Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, rp.Name) == null);
            }

            p.AddTopLevelDeclaration(reProcInt);
            p.AddTopLevelDeclaration(reProcBool);
            p.AddTopLevelDeclarations(typeToRecordProc.Values);

            var tmainimpl = BoogieUtil.findProcedureImpl(p.TopLevelDeclarations, p.mainProcName);

            if (!QKeyValue.FindBoolAttribute(tmainimpl.Attributes, "entrypoint"))
            {
                tmainimpl.AddAttribute("entrypoint");
            }

            var program = new PersistentCBAProgram(p, p.mainProcName, 0);
            //program.writeToFile("beforeverify.bpl");
            var vp = new VerificationPass(true);

            vp.run(program);

            success = vp.success;
            if (success)
            {
                return(null);
            }

            var trace = mapBackTraceRecord(vp.trace);

            RestrictToTrace.addConcretization            = true;
            RestrictToTrace.addConcretizationAsConstants = true;
            var tinfo = new InsertionTrans();
            var rt    = new RestrictToTrace(modInpProg, tinfo);

            rt.addTrace(trace);
            RestrictToTrace.addConcretization            = false;
            RestrictToTrace.addConcretizationAsConstants = false;

            var rtprog = rt.getProgram();

            // Build a map of where the alloc constants are from
            allocConstants = rt.concretizeConstantToCall;

            // Add symbolic constants for angelic map havocs
            var newDecls = new List <Constant>();

            rtprog.TopLevelDeclarations.OfType <Implementation>().Iter(impl =>
                                                                       impl.Blocks.Iter(b => instrumentMapHavocs(b, allocConstants, newDecls)));
            rtprog.AddTopLevelDeclarations(newDecls);

            /*
             * foreach (var impl in rtprog.TopLevelDeclarations.OfType<Implementation>())
             * {
             *  // strip _trace from the impl name
             *  var implName = impl.Name;
             *  var c = implName.LastIndexOf("_trace");
             *  while (c != -1)
             *  {
             *      implName = implName.Substring(0, c);
             *      c = implName.LastIndexOf("_trace");
             *  }
             *
             *  var vu = new VarsUsed();
             *  vu.VisitImplementation(impl);
             *  vu.varsUsed.Where(s => s.StartsWith("alloc_"))
             *      .Iter(s => allocConstants[s] = implName);
             * }
             */
            BoogieUtil.findProcedureImpl(rtprog.TopLevelDeclarations, rt.getFirstNameInstance(p.mainProcName))
            .AddAttribute("entrypoint");

            program = new PersistentCBAProgram(rtprog, rt.getFirstNameInstance(p.mainProcName), p.contextBound);

            // Lets inline it all
            var inlp = new InliningPass(1);

            program = inlp.run(program);

            var compress = new CompressBlocks();
            var ret      = program.getProgram();

            compress.VisitProgram(ret);


            return(new CBAProgram(ret, program.mainProcName, 0));
        }
Beispiel #2
0
        // Verify prog while tracking only variables in trackedVars.
        // Returns true if no error is found.
        // Returns false if error is found. Returns counterexample via pout
        // If returnTrace is set to false, then pout is always null
        //     (no counterexample generation is attempted)
        // cex: the error trace in prog (if there is one)
        // tinfo: the transformation carried out in going from prog to pout
        // Call this method via: checkProgram or checkPath
        private static bool VerifyProgram(ref PersistentCBAProgram prog, VarSet trackedVars, bool returnTrace,
                                          out PersistentCBAProgram pout, out InsertionTrans tinfo, out ErrorTrace cex)
        {
            PersistentCBAProgram curr = prog;

            pout  = null;
            cex   = null;
            tinfo = null;

            //////
            // These are the compilation phases
            //////

            VariableSlicePass        cp1 = new VariableSlicePass(trackedVars);
            StormInstrumentationPass cp2 = null;
            var recordK = new HashSet <string>();

            if (!GlobalConfig.isSingleThreaded)
            {
                cp2 = new StormInstrumentationPass();
            }

            StaticInliningAndUnrollingPass cp3 = null;

            if (GlobalConfig.staticInlining > 0)
            {
                cp3 = new StaticInliningAndUnrollingPass(new StaticSettings(CommandLineOptions.Clo.RecursionBound, CommandLineOptions.Clo.RecursionBound));
            }

            ContractInfer ciPass = null;

            // Run the source transformations
            curr = cp1.run(curr);
            if (cp2 != null)
            {
                curr = cp2.run(curr);
            }
            if (cp3 != null)
            {
                curr = cp3.run(curr);
            }

            // infer contracts
            if (GlobalConfig.InferPass != null)
            {
                ciPass = new ContractInfer(GlobalConfig.InferPass);
                ciPass.ExtractLoops = false;
                curr = ciPass.run(curr);
                Console.WriteLine("Houdini took {0} seconds", ciPass.lastRun.TotalSeconds.ToString("F2"));
                GlobalConfig.InferPass = null;

                // add summaries to the original program
                prog = ciPass.addSummaries(prog);
            }

            // record k and tid
            if (cp2 != null)
            {
                recordK.Add(cp2.varKName); recordK.Add(cp2.tidVarName);
            }

            if (GlobalConfig.varsToRecord.Count != 0)
            {
                recordK.UnionWith(GlobalConfig.varsToRecord);
                recordK.IntersectWith(trackedVars.Variables);
            }

            // Now verify
            VerificationPass cp4 = new VerificationPass(true, recordK);

            curr = cp4.run(curr);

            reachedBound = cp4.reachedBound;

            if (cp4.success)
            {
                // Program correct.
                return(true);
            }
            else if (!returnTrace)
            {
                return(false);
            }
            else
            {
                // Concretize the trace and see if its a real bug

                // Concretization: map back the trace to the original program
                var trace4 = cp4.trace;
                //PrintProgramPath.print(cp4.input as PersistentCBAProgram, trace4, "temp4");

                if (ciPass != null)
                {
                    trace4 = ciPass.mapBackTrace(trace4);
                }
                var trace3 = trace4;


                if (cp3 != null)
                {
                    trace3 = cp3.mapBackTrace(trace4);
                }
                //PrintProgramPath.print(cp3.input as PersistentCBAProgram, trace3, "temp3");

                var trace2 = trace3;
                if (cp2 != null)
                {
                    trace2 = cp2.mapBackTrace(trace3);
                }

                var trace1 = cp1.mapBackTrace(trace2);
                //PrintProgramPath.print(cp1.input as PersistentCBAProgram, trace1, "temp1");

                cex = trace1;

                // Restrict the program to the trace
                tinfo = new InsertionTrans();
                var traceProgCons = new RestrictToTrace(cp1.input.getProgram(), tinfo);
                ErrorTrace.fillInContextSwitchInfo(trace1);
                traceProgCons.addTrace(trace1);

                pout =
                    new PersistentCBAProgram(traceProgCons.getProgram(),
                                             traceProgCons.getFirstNameInstance(cp1.getInput().mainProcName),
                                             cp1.getInput().contextBound,
                                             ConcurrencyMode.FixedContext);

                //pout.writeToFile("pout.bpl");
                return(false);
            }
        }