// Assumptions:
        //  - Program has no recursion
        public static HashSet <string> FindLeastToVerify(Program program, HashSet <string> boolVars)
        {
            Debug.Assert(program != null);

            RemoveAsserts(program);

            if (options.printProg)
            {
                BoogieUtil.PrintProgram(program, options.progFileName);
            }

            //// ---------- Verify ----------------------------------------------------------------
            Debug.Assert(CommandLineOptions.Clo.StratifiedInlining > 0);

            VC.StratifiedVCGenBase vcgen = null;
            try
            {
                if (options.newStratifiedInlining)
                {
                    vcgen = new CoreLib.StratifiedInlining(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, null);
                }
                else
                {
                    vcgen = new VC.StratifiedVCGen(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List <Checker>());
                }
            }
            catch (ProverException)
            {
                Log.WriteLine(Log.Error, "ProverException: {0}");
                return(new HashSet <string>());
            }

            var mains = program.TopLevelDeclarations
                        .OfType <Implementation>()
                        .Where(impl => QKeyValue.FindBoolAttribute(impl.Attributes, "entrypoint"));

            if (mains.Count() != 1)
            {
                throw new InternalError("Wrong number of entrypoints for FindLeastToverify");
            }

            var main = mains.First();

            VC.VCGen.Outcome outcome;
            //HashSet<string> minVars = new HashSet<string>();

            try
            {
                var start = DateTime.Now;

                outcome = vcgen.FindLeastToVerify(main, ref boolVars);

                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:
                Debug.Assert(false);
                break;

            case VC.VCGen.Outcome.ReachedBound:
                Debug.Assert(false);
                break;

            case VC.VCGen.Outcome.Inconclusive:
                throw new InternalError("z3 says inconclusive");

            case VC.VCGen.Outcome.OutOfMemory:
                throw new InternalError("z3 out of memory");

            case VC.VCGen.Outcome.TimedOut:
                throw new InternalError("z3 timed out");

            default:
                throw new InternalError("z3 unknown response");
            }
            Debug.Assert(outcome == VC.VCGen.Outcome.Correct);

            vcgen.Close();
            CommandLineOptions.Clo.TheProverFactory.Close();
            return(boolVars);
        }
示例#2
0
        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.vcVariety != CommandLineOptions.VCVariety.Doomed);
                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.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, null);
                }
                else
                // vcgen = new VC.StratifiedVCGen(options.CallTree != null, options.CallTree, options.procsToSkip, options.extraRecBound, program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, 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.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, new List <Checker>());
                }
                else
                {
                    CommandLineOptions.Clo.FixedPointMode   = CommandLineOptions.FixedPointInferenceMode.Corral;
                    CommandLineOptions.Clo.FixedPointEngine = "duality";
                    vcgen = new Microsoft.Boogie.FixedpointVC(program, CommandLineOptions.Clo.SimplifyLogFilePath, CommandLineOptions.Clo.SimplifyLogFileAppend, 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.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);
        }