Beispiel #1
0
            private void CreateMainProcedure(Function reach)
            {
                //blocks
                List <Block>    mainBlocks = new List <Block>();
                List <Variable> locals     = new List <Variable>();

                HashSet <Constant> blockCallConsts = new HashSet <Constant>();

                foreach (Implementation impl in prog.TopLevelDeclarations.Where(x => x is Implementation))
                {
                    // skip this impl if it is not marked as an entrypoint
                    if (useProvidedEntryPoints && !QKeyValue.FindBoolAttribute(impl.Proc.Attributes, "entrypoint"))
                    {
                        continue;
                    }

                    impl.Attributes      = BoogieUtil.removeAttr("entrypoint", impl.Attributes);
                    impl.Proc.Attributes = BoogieUtil.removeAttr("entrypoint", impl.Proc.Attributes);

                    // skip initialization procedure
                    if (QKeyValue.FindBoolAttribute(impl.Attributes, AvnAnnotations.InitialializationProcAttr) ||
                        QKeyValue.FindBoolAttribute(impl.Proc.Attributes, AvnAnnotations.InitialializationProcAttr))
                    {
                        continue;
                    }

                    entrypoints.Add(impl.Name);

                    //allocate params
                    var args = new List <Variable>();
                    var rets = new List <Variable>();


                    impl.OutParams.ForEach(v => rets.Add(BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type)));
                    if (Options.allocateParameters)
                    {
                        // use impl.Proc here to pickup scalar/pointer attributes
                        impl.Proc.InParams.ForEach(v =>
                        {
                            var l = BoogieAstFactory.MkLocal(v.Name + "_" + impl.Name, v.TypedIdent.Type);
                            // We are delibrately dropping the attributes so that
                            // all parameters are initialized by allocation
                            //l.Attributes = v.Attributes;
                            args.Add(l);
                        });
                        locals.AddRange(args);
                    }
                    else
                    {
                        impl.Proc.InParams.ForEach(v =>
                        {
                            var g = BoogieAstFactory.MkGlobal(v.Name + "_" + impl.Name, v.TypedIdent.Type);
                            //g.Attributes = v.Attributes;
                            args.Add(g);
                        });
                        globalParams.AddRange(args);
                    }


                    locals.AddRange(rets);

                    //call
                    var blockCallConst = new Constant(Token.NoToken,
                                                      new TypedIdent(Token.NoToken, "__block_call_" + impl.Name, btype.Bool), false);
                    blockCallConsts.Add(blockCallConst);
                    blockEntryPointConstants[blockCallConst.Name] = impl.Name;
                    impl2BlockingConstant[impl.Name] = blockCallConst;
                    var blockCallAssumeCmd = new AssumeCmd(Token.NoToken, IdentifierExpr.Ident(blockCallConst));

                    var cmds = new List <Cmd>();
                    cmds.Add(blockCallAssumeCmd);
                    if (Options.allocateParameters) // allocate parameters if option is enabled
                    {
                        var argMallocCmds = AllocatePointersAsUnknowns(args);
                        cmds.AddRange(argMallocCmds);
                    }

                    // The beginning of an entry point must be reachable: assume reach(true);
                    cmds.Add(new AssumeCmd(Token.NoToken, new NAryExpr(Token.NoToken,
                                                                       new FunctionCall(reach), new List <Expr> {
                        Expr.True
                    })));

                    var callCmd = new CallCmd(Token.NoToken, impl.Name, args.ConvertAll(x => (Expr)IdentifierExpr.Ident(x)),
                                              rets.ConvertAll(x => IdentifierExpr.Ident(x)));
                    callCmd.Attributes = new QKeyValue(Token.NoToken, AvUtil.AvnAnnotations.AvhEntryPointAttr, new List <object>(), callCmd.Attributes);

                    cmds.Add(callCmd);
                    //succ
                    var txCmd = new ReturnCmd(Token.NoToken);
                    var blk   = BoogieAstFactory.MkBlock(cmds, txCmd);
                    mainBlocks.Add(blk);
                }
                foreach (Procedure proc in prog.TopLevelDeclarations.OfType <Procedure>())
                {
                    proc.Attributes = BoogieUtil.removeAttr("entrypoint", proc.Attributes);
                }
                // add global variables to prog
                // globals.Iter(x => prog.AddTopLevelDeclaration(x));
                //add the constants to the prog
                blockCallConsts.Iter(x => prog.AddTopLevelDeclaration(x));
                //TODO: get globals of type refs/pointers and maps
                var initCmd = (AssumeCmd)BoogieAstFactory.MkAssume(Expr.True);

                var globalCmds = new List <Cmd>()
                {
                    initCmd
                };
                //add call to corralExtraInit
                var init = Instrumentations.GetEnvironmentAssumptionsProc(prog);

                if (init != null && !Options.DelayInitialization)
                {
                    globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>()));
                }

                // Dont initialize Boogie instrumentation variables
                prog.GlobalVariables
                .Where(g => g.Name == "alloc" || BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes))
                .Where(g => !BoogieUtil.checkAttrExists("scalar", g.Attributes))
                .Iter(g => g.AddAttribute("scalar"));

                // initialize globals
                prog.GlobalVariables
                .Where(g => g.Name != "alloc" && !BoogieUtil.checkAttrExists(AvnAnnotations.AllocatorVarAttr, g.Attributes))
                .Iter(g => g.Attributes = BoogieUtil.removeAttrs(new HashSet <string> {
                    "scalar", "pointer"
                }, g.Attributes));

                globalCmds.AddRange(AllocatePointersAsUnknowns(prog.GlobalVariables.Select(x => (Variable)x).ToList()));

                if (init != null && Options.DelayInitialization)
                {
                    globalCmds.Add(BoogieAstFactory.MkCall(init, new List <Expr>(), new List <Variable>()));
                }

                // globals for parameters
                prog.AddTopLevelDeclarations(globalParams);

                //first block
                var transferCmd =
                    mainBlocks.Count > 0 ? (TransferCmd)(new GotoCmd(Token.NoToken, mainBlocks)) : (TransferCmd)(new ReturnCmd(Token.NoToken));
                Block blkStart = new Block(Token.NoToken, "CorralMainStart", globalCmds, transferCmd);
                var   blocks   = new List <Block>();

                blocks.Add(blkStart);
                blocks.AddRange(mainBlocks);
                var mainProcImpl = BoogieAstFactory.MkImpl(AvnAnnotations.CORRAL_MAIN_PROC, new List <Variable>(), new List <Variable>(), locals, blocks);

                mainProcImpl[0].AddAttribute("entrypoint");
                prog.AddTopLevelDeclarations(mainProcImpl);
            }
Beispiel #2
0
        private static void addSummaryPredicate()
        {
            if (!System.IO.File.Exists("corralPredicates.txt"))
            {
                return;
            }

            // stubs is always [] in the current version.
            var predWithStubs = new HashSet <Tuple <string, string> >();

            using (var file = new System.IO.StreamReader("corralPredicates.txt"))
            {
                string pred;
                string stubs = "";
                while ((pred = file.ReadLine()) != null)
                {
                    if (useStubs)
                    {
                        stubs = file.ReadLine();
                        if (stubs == "[]")
                        {
                            stubs = "";
                        }
                        else
                        {
                            stubs = string.Format("{{:stubs \"{0}\"}}", stubs);
                        }
                    }
                    predWithStubs.Add(Tuple.Create(stubs, pred));
                }
            }

            string database = CommonLib.GlobalConfig.util_result_file;

            Debug.Assert(!System.IO.File.Exists(database));
            var summaries = new StubAnnotatedSummaryDictionary();

            StubAnnotatedSummaryDictionary.CreateProver(z3exe);
            if (useStubs)
            {
                predWithStubs.Iter(tup => summaries.Add(tup.Item1, tup.Item2));
            }
            else
            {
                predWithStubs.Iter(tup => summaries.Add("", tup.Item2));
            }
            //predicates.Iter(pred => summaries.Add(property, pred));
            //summaries.Print(databaseTxt);
            StubAnnotatedSummaryDictionary.CloseProver();
            summaries.Marshall();

            while (true)
            {
                try
                {
                    using (var fs = new System.IO.FileStream(database, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None))
                    {
                        var serializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                        serializer.Serialize(fs, summaries);
                        break;
                    }
                }
                catch (System.IO.IOException)
                {
                    Random rnd = new Random();
                    Thread.Sleep(rnd.Next(300, 501));
                }
            }
            if (debugging)
            {
                Console.WriteLine("Dumped summaries to db.");
            }
        }
Beispiel #3
0
            private void FindUnknown()
            {
                // Which {:unknown} already exist?
                foreach (var proc in prog.TopLevelDeclarations.OfType <Procedure>()
                         .Where(p => QKeyValue.FindBoolAttribute(p.Attributes, AvnAnnotations.AngelicUnknownCall)))
                {
                    if (proc.OutParams.Count != 1 || proc.InParams.Count != 0)
                    {
                        continue;
                    }
                    //throw new InputProgramDoesNotMatchExn(string.Format("Unknown-generating procs should have exactly one out parameter and no input parameters: {0}", proc.Name));
                    unknownGenProcs.Add(proc.OutParams[0].TypedIdent.Type.ToString(), proc);
                }

                foreach (var ty in Options.unknownTypes)
                {
                    // Find the type
                    btype type = null;
                    if (ty == "int")
                    {
                        type = btype.Int;
                    }
                    else if (ty == "bool")
                    {
                        type = btype.Bool;
                    }
                    else if (ty == "[int]int")
                    {
                        type = new MapType(Token.NoToken, new List <TypeVariable>(), new List <btype> {
                            btype.Int
                        }, btype.Int);
                    }
                    else
                    {
                        // lookup user types
                        type = prog.TopLevelDeclarations.OfType <TypeCtorDecl>()
                               .Where(t => t.Name == ty)
                               .Select(t => new CtorType(Token.NoToken, t, new List <btype>()))
                               .FirstOrDefault();

                        if (type == null)
                        {
                            type = prog.TopLevelDeclarations.OfType <TypeSynonymDecl>()
                                   .Where(t => t.Name == ty)
                                   .Select(t => new TypeSynonymAnnotation(Token.NoToken, t, new List <btype>()))
                                   .FirstOrDefault();
                        }
                    }
                    if (type == null)
                    {
                        Console.WriteLine("Error: type {0} not found", type);
                        throw new InputProgramDoesNotMatchExn("Invalid unknown type given");
                    }

                    if (unknownGenProcs.ContainsKey(ty))
                    {
                        continue;
                    }

                    // create a new procedure
                    var proc = new Procedure(Token.NoToken, "unknown_" + SanitizeTypeName(type), new List <TypeVariable>(), new List <Variable>(),
                                             new List <Variable> {
                        new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "r", type), false)
                    },
                                             new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>());
                    proc.AddAttribute(AvnAnnotations.AngelicUnknownCall);
                    unknownGenProcs.Add(ty, proc);
                    prog.AddTopLevelDeclaration(proc);
                }

                // Remove extra ones
                var extra = new HashSet <string>(unknownGenProcs.Keys);

                extra.ExceptWith(Options.unknownTypes);
                extra.Iter(s => unknownGenProcs.Remove(s));

                foreach (var proc in unknownGenProcs.Values)
                {
                    // Add {:allocator "full"} annotation
                    var attr = QKeyValue.FindStringAttribute(proc.Attributes, "allocator");
                    if (attr != null && attr == "full")
                    {
                        continue;
                    }
                    proc.AddAttribute("allocator", "full");

                    // Drop Requires/Ensures
                    proc.Requires = new List <Requires>();
                    proc.Ensures  = new List <Ensures>();
                    proc.Modifies = new List <IdentifierExpr>();
                }

                // Extra annotations for user-defined unknowns
                prog.TopLevelDeclarations.OfType <Procedure>()
                .Where(p => Options.unknownProcs.Contains(p.Name))
                .Iter(p => p.AddAttribute(AvnAnnotations.AngelicUnknownCall));
            }
Beispiel #4
0
        static void ComputeandInitializeUninitializedLocals(Program program)
        {
            var mallocFull = FindMalloc(program);

            if (mallocFull == null)
            {
                Console.WriteLine("No malloc procedure found -- cannot initialize uninitialized locals");
                return;
            }

            foreach (Implementation impl in program.TopLevelDeclarations.OfType <Implementation>())
            {
                impl.ComputePredecessorsForBlocks(); // will be used for uninitialized variable analysis

                // set of local variables in implementation
                HashSet <string> locVars = new HashSet <string>(impl.LocVars.Where(v => !v.TypedIdent.Type.IsMap).Select(v => v.Name));

                // we will initialize these variables in the end
                HashSet <string> uninitializedVars = new HashSet <string>();

                // will be used to perform fixed point iteration on blocks, CFG traversal is DFS
                Dictionary <string, bool> changedBlocks = new Dictionary <string, bool>();
                impl.Blocks.Iter(b => changedBlocks[b.Label] = false);

                // blk -> variables uninitialized at the end of blk
                Dictionary <string, HashSet <string> > LIVE_out = new Dictionary <string, HashSet <string> >();
                impl.Blocks.Iter(b => LIVE_out[b.Label] = new HashSet <string>());

                Block entry = impl.Blocks[0];

                Func <Cmd, HashSet <string>, HashSet <string> > ProcessCmd = new Func <Cmd, HashSet <string>, HashSet <string> >((cmd, variables) =>
                {
                    HashSet <string> readVars  = GetReadVars(cmd);
                    HashSet <string> writeVars = GetWriteVars(cmd);

                    // variable being read before written
                    readVars.IntersectWith(variables);
                    uninitializedVars.UnionWith(readVars);

                    // remove written variables from variables
                    variables.ExceptWith(writeVars);

                    return(variables);
                });

                Action <Block> ProcessBlock = new Action <Block>(b =>
                {
                    var live_vars = new HashSet <string>();

                    // taking union of all predecessors
                    if (b.Label.Equals(entry.Label))
                    {
                        locVars.Iter(v => live_vars.Add(v));
                    }
                    else
                    {
                        b.Predecessors.Iter(block => live_vars.UnionWith(LIVE_out[block.Label]));
                    }

                    foreach (Cmd c in b.Cmds)
                    {
                        live_vars = ProcessCmd(c, live_vars);
                    }

                    if (!live_vars.SetEquals(LIVE_out[b.Label]))
                    {
                        changedBlocks[b.Label] = true;
                    }
                    else
                    {
                        changedBlocks[b.Label] = false;
                    }

                    LIVE_out[b.Label] = live_vars;
                });

                Stack <Block> blockList = new Stack <Block>();
                blockList.Push(entry);

                while (blockList.Count > 0)
                {
                    var blk = blockList.Pop();

                    ProcessBlock(blk);

                    if (blk.TransferCmd is GotoCmd && changedBlocks[blk.Label])
                    {
                        var gtc = blk.TransferCmd as GotoCmd;
                        foreach (Block succ in gtc.labelTargets)
                        {
                            blockList.Push(succ);
                        }
                    }
                }

                // list of variables to be initialized completed
                IEnumerable <Variable> tobeInitialized = impl.LocVars.Where(v => uninitializedVars.Contains(v.Name));
                tobeInitialized = tobeInitialized.Union(impl.OutParams);

                // now initializing
                List <Cmd> cmds = new List <Cmd>();

                foreach (Variable v in tobeInitialized)
                {
                    Cmd cmd = AllocatePointerAsUnknown(mallocFull, v);
                    cmds.Add(cmd);
                }

                Block init = new Block(Token.NoToken, "init", cmds, new GotoCmd(Token.NoToken, new List <Block> {
                    entry
                }));

                List <Block> newblocks = new List <Block>();
                newblocks.Add(init);
                impl.Blocks.Iter(blk => newblocks.Add(blk));

                impl.Blocks = newblocks;
            }
        }
Beispiel #5
0
        private ICEOutcome LearnInvFromTemplate(Dictionary<string, int> impl2Priority, Template t, int range, out VCGenOutcome overallOutcome)
        {
            overallOutcome = null;

            // create a new z3 context
            if (z3Context != null)
            {
                z3Context.context.Dispose();
                z3Context.config.Dispose();
            }
            z3Context = new Z3Context();

            foreach (var func in existentialFunctions.Values)
            {
                // initialize function to an "Octagons" instance with the given template "t".
                function2Value[func.Name] = ICEDomainFactory.GetInstance("Octagons", t, ref z3Context, func.Name, range);
            }

            // add counterexamples into the z3Context. These are obtained from the earlier iterations of the template.
            foreach (var cex in counterExamples)
            {
                AddCounterExampleToZ3Context(cex);
            }

            var worklist = new SortedSet<Tuple<int, string>>();
            name2Impl.Keys.Iter(k => worklist.Add(Tuple.Create(impl2Priority[k], k)));

            while (worklist.Any())
            {
                var impl = worklist.First().Item2;
                worklist.Remove(worklist.First());

                #region vcgen

                var gen = prover.VCExprGen;
                var terms = new List<Expr>();
                foreach (var tup in impl2FuncCalls[impl])
                {
                    var controlVar = tup.Item2;
                    var exprVars = tup.Item3;
                    var varList = new List<Expr>();
                    exprVars.Args.OfType<Expr>().Iter(v => varList.Add(v));

                    var args = new List<Expr>();
                    controlVar.InParams.Iter(v => args.Add(Expr.Ident(v)));
                    Expr term = Expr.Eq(new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args),
                                 function2Value[tup.Item1].Gamma(varList));

                    if (controlVar.InParams.Count != 0)
                    {
                        term = new ForallExpr(Token.NoToken, new List<Variable>(controlVar.InParams.ToArray()),
                            new Trigger(Token.NoToken, true, new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args) }),
                            term);
                    }
                    terms.Add(term);
                }
                var env = BinaryTreeAnd(terms, 0, terms.Count - 1);

                env.Typecheck(new TypecheckingContext((IErrorSink)null));
                var envVC = prover.Context.BoogieExprTranslator.Translate(env);

                var vc = gen.Implies(envVC, impl2VC[impl]);

                if (CommandLineOptions.Clo.Trace)
                {
                    Console.WriteLine("Verifying {0}: ", impl);
                    //Console.WriteLine("env: {0}", envVC);
                    var envFuncs = new HashSet<string>();
                    impl2FuncCalls[impl].Iter(tup => envFuncs.Add(tup.Item1));
                    envFuncs.Iter(f => PrintFunction(existentialFunctions[f]));
                }

                #endregion vcgen

                VCExpr finalVC;

                #region bound_value_of_cexs
            #if false
                finalVC = vc;

            #else
                int bound = 1000000;
                terms.Clear();
                foreach (var tup in impl2FuncCalls[impl])
                {
                    var exprVars = tup.Item3;
                    var varList = new List<Expr>();
                    exprVars.Args.OfType<Expr>().Where(v => v.Type.IsInt).Iter(v => varList.Add(v));
                    foreach (var variable in varList)
                    {
                        terms.Add(Expr.Le(variable, Expr.Literal(bound)));
                        terms.Add(Expr.Ge(variable, Expr.Literal(-1 * bound)));
                        //terms.Add(Expr.Ge(variable, Expr.Literal(0)));
                    }
                }
                var boundcex = BinaryTreeAnd(terms, 0, terms.Count - 1);
                boundcex.Typecheck(new TypecheckingContext((IErrorSink)null));
                var boundcexVC = prover.Context.BoogieExprTranslator.Translate(boundcex);

                finalVC = gen.Implies(boundcexVC, vc);
            #endif
                #endregion bound_value_of_cexs

                var handler = impl2ErrorHandler[impl].Item1;
                var collector = impl2ErrorHandler[impl].Item2;
                collector.Reset(impl);
                VCisValid = true;   // set to false if control reaches HandleCounterExample
                realErrorEncountered = false;
                newSamplesAdded = false;

                var start = DateTime.Now;

                prover.Push();
                prover.Assert(gen.Not(finalVC), true);
                prover.FlushAxiomsToTheoremProver();
                prover.Check();
                ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler);

                //prover.BeginCheck(impl, vc, handler);
                //ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler);

                var inc = (DateTime.Now - start);
                proverTime += inc;
                numProverQueries++;

                if (CommandLineOptions.Clo.Trace)
                    Console.WriteLine("Prover Time taken = " + inc.TotalSeconds.ToString());

                if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
                {
                    Console.WriteLine("Z3 Prover for implementation {0} times out or runs out of memory !", impl);
                    z3Context.context.Dispose();
                    z3Context.config.Dispose();

                    overallOutcome = new VCGenOutcome(proverOutcome, new List<Counterexample>());
                    return ICEOutcome.Timeout;
                }

                if (CommandLineOptions.Clo.Trace)
                    Console.WriteLine(!VCisValid ? "SAT" : "UNSAT");

                if (!VCisValid)
                {
                    if (realErrorEncountered)
                    {
                        overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.real_errors);
                        return ICEOutcome.ErrorFound;
                    }

                    Debug.Assert(newSamplesAdded);
                    HashSet<string> funcsChanged;
                    if (!learn(out funcsChanged))
                    {
                        // learner timed out or there is no valid conjecture in the current given template
                        overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.conjecture_errors);
                        prover.Pop();
                        return ICEOutcome.InvariantNotFound;
                    }
                    // propagate dependent guys back into the worklist, including self
                    var deps = new HashSet<string>();
                    deps.Add(impl);
                    funcsChanged.Iter(f => deps.UnionWith(function2implAssumed[f]));
                    funcsChanged.Iter(f => deps.UnionWith(function2implAsserted[f]));

                    deps.Iter(s => worklist.Add(Tuple.Create(impl2Priority[s], s)));
                }

                prover.Pop();
            }
            // The program was verified with the current template!
            overallOutcome = new VCGenOutcome(ProverInterface.Outcome.Valid, new List<Counterexample>());
            return ICEOutcome.InvariantFound;
        }
Beispiel #6
0
 public void CheckCandidateAsserts()
 {
     FindCandidateAsserts();
     houdiniConsts.Iter(x => CheckCandidateAssert(x));
 }
            private void ComputeTransitiveModSets()
            {
                var UpdateTransitiveEdge = new Action <Block, Block, Block>((b1, b2, b3) =>
                {
                    CheckTimeout();
                    Debug.Assert(b1 != null && b2 != null && b3 != null);
                    //mod(b1,b2) + b2.mod + mod(b2,b3)
                    var vs1       = intraProcPairBlockModSet[Tuple.Create(b1, b2)];
                    var vs2       = intraProcPairBlockModSet[Tuple.Create(b2, b3)];
                    var vs3       = modSetBlock[b2]; //add b2's modset
                    var vs        = vs1.Union(vs2.Union(vs3));
                    int prevCount = 0;
                    var b1b3      = Tuple.Create(b1, b3);
                    if (intraProcPairBlockModSet.ContainsKey(b1b3))
                    {
                        prevCount = intraProcPairBlockModSet[b1b3].Count;
                    }
                    else
                    {
                        intraProcPairBlockModSet[b1b3] = new HashSet <Variable>();
                    }
                    var newvs = new HashSet <Variable>();
                    vs.Union(intraProcPairBlockModSet[b1b3]).Iter(x => newvs.Add(x));
                    if (newvs.Count > prevCount)     //add if previously not present or weight has changed
                    {
                        newvs.Iter(x => intraProcPairBlockModSet[b1b3].Add(x));
                        if (!workList.Contains(b1b3))
                        {
                            workList.Add(b1b3);
                        }
                    }
                }
                                                                            );

                int i = 1;
                //hash the lookups
                Dictionary <Block, HashSet <Block> > predStart = new Dictionary <Block, HashSet <Block> >();
                Dictionary <Block, HashSet <Block> > succEnd   = new Dictionary <Block, HashSet <Block> >();
                int skippedCount = 0;

                while (workList.Count() > 0)
                {
                    var blkPair = workList.ElementAt(0);
                    workList.Remove(blkPair);
                    var start = blkPair.Item1;
                    var end   = blkPair.Item2;
                    Debug.Assert(!IsChainBlock(start));
                    Debug.Assert(!IsChainBlock(end));
                    bool addPredStart = false, addSuccEnd = false;
                    //check if we have already seen this pair or not
                    if (!predStart.ContainsKey(start))
                    {
                        addPredStart = true; predStart[start] = new HashSet <Block>();
                    }
                    if (!succEnd.ContainsKey(end))
                    {
                        addSuccEnd = true; succEnd[end] = new HashSet <Block>();
                    }
                    if (addPredStart || addSuccEnd)
                    {
                        //foreach (var succ in successorBlocks)
                        foreach (var succ in mergeJoinSuccessors)
                        {
                            //succ->start + start->end --> succ->end
                            if (succ.Value.Contains(start) && addPredStart)
                            {
                                predStart[start].Add(succ.Key);
                            }
                            //start->end + end->d      --> start->d
                            if (succ.Key == end && addSuccEnd)
                            {
                                succ.Value.Iter(d => succEnd[end].Add(d));
                            }
                        }
                    }
                    else
                    {
                        skippedCount++; //we are able to skip the expensive construction of succ/pred relation
                    }
                    predStart[start].Iter(x => UpdateTransitiveEdge(x, start, end));
                    succEnd[end].Iter(x => UpdateTransitiveEdge(start, end, x));
                    i++;
                }
                //Console.WriteLine("|WL| = {0}, |succBlocks| = {1}, SkippedCount = {2}", i, successorBlocks.Count, skippedCount);
            }
Beispiel #8
0
        private void InferWhatToCut(Graph <string> graph, IEnumerable <string> scc)
        {
            Debug.Assert(backedges != null);
            smallcutset = null;

            //someCycles.Iter(c => Console.WriteLine("Cycle: {0}", c.Print()));

            // If small number of backedges, then done
            if (backedges.Count <= 2)
            {
                return;
            }

            var cutset = new HashSet <string>();
            var weight = new Dictionary <int, HashSet <string> >();

            backedges.Iter(tup => cutset.Add(tup.Item2));

            // how many cycles does s appear in?
            foreach (var s in cutset)
            {
                var cnt = 0;
                someCycles.Where(c => c.Contains(s)).Iter(c => cnt++);
                if (!weight.ContainsKey(cnt))
                {
                    weight.Add(cnt, new HashSet <string>());
                }
                weight[cnt].Add(s);
            }


            // take the highest-weight nodes

            smallcutset = new HashSet <string>();
            var cycleCnt = someCycles.Count;

            // Is there a cutset of size 1?
            if (weight.ContainsKey(cycleCnt) && weight[cycleCnt].Count > 0)
            {
                smallcutset.Add(weight[cycleCnt].First());
            }
            else
            {
                // Is there a cutset of size 2?
                for (int i = cycleCnt; i >= 0; i++)
                {
                    if (!weight.ContainsKey(i))
                    {
                        continue;
                    }
                    foreach (var s in weight[i])
                    {
                        if (smallcutset.Contains(s))
                        {
                            continue;
                        }
                        if (smallcutset.Count >= 2)
                        {
                            continue;
                        }
                        smallcutset.Add(s);
                    }
                }
            }

            // Is smallcutset a cutset?
            var domain = new HashSet <string>(scc);

            domain.ExceptWith(smallcutset);
            if (isAcyclic(graph, domain))
            {
                Console.WriteLine("Found small cutset: {0}", smallcutset.Print());
                backedges = null;
            }
            else
            {
                smallcutset = null;
                Console.WriteLine("Using {0} backedges to cut cycles", backedges.Count);
            }
        }
Beispiel #9
0
        private List <Cmd> AbstractAssign(AssignCmd acmd)
        {
            var newcmd = new List <Cmd>();

            // !KeepSimple: then map indices are given special treatment
            var KeepSimple = UseSimpleSlicing || (currImplementation == null) || (acmd.Lhss.Count != 1);

            if (acmd.Lhss.Count != 1)
            {
                EncounteredParallelAssignment = true;
            }

            var newLhss     = new List <AssignLhs>();
            var newRhss     = new List <Expr>();
            var varsToHavoc = new HashSet <Variable>();

            for (int i = 0; i < acmd.Lhss.Count; i++)
            {
                AssignLhs lhs = acmd.Lhss[i];
                Expr      rhs = acmd.Rhss[i];

                //IdentifierExpr assignedVar = getAssignedVariable(lhs);
                IdentifierExpr assignedVar = lhs.DeepAssignedIdentifier;

                if (isTrackedVariable(assignedVar.Decl))
                {
                    if (lhs is MapAssignLhs && !indicesAreTracked((MapAssignLhs)lhs))
                    {
                        // convert to assignedVar := *
                        varsToHavoc.Add(assignedVar.Decl);
                    }
                    else if (!isTracked(rhs))
                    {
                        // Convert to lhs := *
                        if (KeepSimple || lhs is SimpleAssignLhs)
                        {
                            varsToHavoc.Add(assignedVar.Decl);
                        }
                        else
                        {
                            // convert to "havoc lhs" as follows:
                            // havoc dummy; lhs := dummy;
                            // This is done when lhs is Mem[x]. We're not
                            // allowed to say "havoc Mem[x]".

                            // We should be doing this only when we can add new
                            // local variables
                            Debug.Assert(currImplementation != null);

                            // Get new local variable dummy
                            LocalVariable dummy = getNewLocal(lhs.Type, currImplementation);

                            // havoc dummy
                            newcmd.Add(BoogieAstFactory.MkHavocVar(dummy));

                            // lhs := dummy
                            newLhss.Add(lhs);
                            newRhss.Add(Expr.Ident(dummy));
                        }
                    }
                    else
                    {
                        // It is possible to come here because a variable may be untracked in this scope,
                        // yet tracked globally because it is on the lhs
                        newLhss.Add(lhs);
                        newRhss.Add(rhs);
                    }
                }
            }

            if (newLhss.Count != 0)
            {
                newcmd.Add(new AssignCmd(Token.NoToken, newLhss, newRhss));
            }

            if (varsToHavoc.Count != 0)
            {
                var ieseq = new List <IdentifierExpr>();
                varsToHavoc.Iter(v => ieseq.Add(Expr.Ident(v)));
                newcmd.Add(new HavocCmd(Token.NoToken, ieseq));
            }

            return(newcmd);
        }
Beispiel #10
0
        public static bool ApplyTemplates(HashSet <int> templates)
        {
            var commonGlobals = Minimize.FindCommonGlobals();
            var ret           = false;

            // Prune away ones that don't have constants associated with them
            templates = new HashSet <int>(
                templates.Where(t => !templateMap[t].All(tup => tup.Value.SetEquals(fileToKeepConstants[tup.Key]))));

            // Prune away ones that don't talk about common globals
            templates = new HashSet <int>(
                templates.Where(t =>
            {
                var expr = SimplifyExpr.ToExpr(templateToStr[t]);
                var vu   = new GlobalVarsUsed();
                vu.VisitExpr(expr);
                return(vu.globalsUsed.IsSubsetOf(commonGlobals));
            }));

            var newFileToProg = new Dictionary <string, PersistentProgram>();

            var templateToConstants = new Dictionary <int, int>();

            templates.Iter(t => templateToConstants.Add(t, 0));

            foreach (var tup in fileToProg)
            {
                var program = tup.Value.getProgram();
                BoogieUtil.DoModSetAnalysis(program);
                var globals = new HashSet <string>(program.TopLevelDeclarations.OfType <GlobalVariable>().Select(g => g.Name));

                var newconstants = new HashSet <Constant>();

                foreach (var t in templates)
                {
                    var expr   = SimplifyExpr.ToExpr(templateToStr[t]);
                    var nonold = new GatherNonOldVariables();
                    nonold.VisitExpr(expr);

                    var mustmod = new HashSet <string>(nonold.variables);
                    mustmod.IntersectWith(globals);

                    foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
                    {
                        var mod = new HashSet <string>(impl.Proc.Modifies.Select(ie => ie.Name));
                        if (!mustmod.IsSubsetOf(mod))
                        {
                            continue;
                        }

                        // create new constant
                        var nc = new Constant(Token.NoToken, new TypedIdent(Token.NoToken, "PMnewConst" + (NewConstCounter++),
                                                                            btype.Bool), false);
                        nc.AddAttribute("existential");
                        newconstants.Add(nc);
                        if (!templateMap[t].ContainsKey(tup.Key))
                        {
                            templateMap[t].Add(tup.Key, new HashSet <string>());
                        }
                        templateMap[t][tup.Key].Add(nc.Name);

                        ret = true;
                        templateToConstants[t]++;

                        impl.Proc.Ensures.Add(new Ensures(false, Expr.Imp(Expr.Ident(nc), expr)));
                    }
                }

                program.AddTopLevelDeclarations(newconstants);
                newFileToProg.Add(tup.Key, new PersistentProgram(program));
            }
            fileToProg = newFileToProg;

            foreach (var tup in templateToConstants)
            {
                Console.WriteLine("Applying template {0}: {1} ({2} constants created)", tup.Key, templateToStr[tup.Key], tup.Value);
            }

            return(ret);
        }
 public RewriteConstants(HashSet <Variable> newConstants)
 {
     this.newConstantsMap = new Dictionary <string, Variable>();
     newConstants.Iter(x => this.newConstantsMap[x.Name] = x);
 }
Beispiel #12
0
            private bool AnalyzeUsingUnsatCore(VCExpr programVC)
            {
                #region Description of UNSAT core logic implemented below

                /*
                 *      Given VC, B
                 *      - pre = (\wedge_{b \in B} b)
                 *      - checkValid preInp => VC
                 *      - if invalid ABORT
                 *      - A += !VC'
                 *      - A += B
                 *      - if (CheckAssumption(A, out core) != valid) ABORT
                 *      - return {b | b in core } as the (super) set of tainted vars
                 */
                #endregion

                List <Counterexample> cexs;

                var outcome = SymDiffVC.VerifyVC("RefinedStmtTaint", programVC, out cexs);
                if (outcome == ProverInterface.Outcome.Valid)
                {
                    Console.WriteLine("Program is already equivalent!!");
                    return(false);
                }

                //mapping of VCExpr
                Dictionary <VCExpr, Constant> vcexprsToConsts = new Dictionary <VCExpr, Constant>();
                taintGuardConsts.Iter(c => { vcexprsToConsts[SymDiffVC.translator.LookupVariable(c)] = c; });

                var preInp = taintGuardConsts
                             .Aggregate(VCExpressionGenerator.True, (x, y) => SymDiffVC.exprGen.And(x, SymDiffVC.translator.LookupVariable(y)));
                var newVC = SymDiffVC.exprGen.Implies(preInp, programVC);

                outputTaintedConstants = new HashSet <Constant>();
                //Should call VerifyVC before invoking CheckAssumptions
                outcome = SymDiffVC.VerifyVC("RefinedStmtTaint", newVC, out cexs);
                Console.Write("-");
                if (outcome == ProverInterface.Outcome.Invalid)
                {
                    Console.WriteLine("\t VC not valid even when all assigns are off, returning");
                    return(false);
                }
                if (outcome == ProverInterface.Outcome.OutOfMemory ||
                    outcome == ProverInterface.Outcome.TimeOut ||
                    outcome == ProverInterface.Outcome.Undetermined)
                {
                    Console.WriteLine("\t VC inconclusive, returning");
                    return(false);
                }

                var assumptions = new List <VCExpr>();
                assumptions.Add(SymDiffVC.exprGen.Not(programVC));
                //Add the list of all input constants
                taintGuardConsts.Iter(x => assumptions.Add(SymDiffVC.translator.LookupVariable(x)));

                var core = AnalyzeUsingUnsatCoreHelper(programVC, ref cexs, ref outcome, ref preInp, assumptions);
                Console.WriteLine("\nNumber of possibly tainted stmts / number of stmts = {0}/{1}", core.Count, taintGuardConsts.Count() / 2 /* one version */);
                Console.WriteLine("\nThe list of taintedStmts are {0}", string.Join(",", core));
                var allBlks     = GatherProcedureBlocksInConstants(taintGuardConsts);
                var taintedBlks = GatherProcedureBlocksInConstants(core.Select(c => vcexprsToConsts[c]));
                Console.WriteLine("\nNumber of possibly tainted blocks / number of blocks = {0}/{1}", taintedBlks.Count, allBlks.Count);

                return(true);
            }
Beispiel #13
0
        static int Main(string[] args)

        {
            if (args.Length < 1)
            {
                Usage();
                return(-1);
            }

            sw = new Stopwatch();
            sw.Start();

            CommandLineOptions.Install(new CommandLineOptions());
            CommandLineOptions.Clo.RunningBoogieFromCommandLine = true;
            var boogieOptions = "/typeEncoding:m -timeLimit:20 -removeEmptyBlocks:0 /printModel:1 /printModelToFile:model.dmp /printInstrumented "; // /errorLimit:1";

            //IMPORTANT: need the next to avoid crash while creating prover
            CommandLineOptions.Clo.Parse(boogieOptions.Split(' '));
            //IMPORTANT: need these three to make use of UNSAT cores!!
            CommandLineOptions.Clo.UseUnsatCoreForContractInfer = true; //ROHIT
            CommandLineOptions.Clo.ContractInfer  = true;               //ROHIT
            CommandLineOptions.Clo.ExplainHoudini = true;

            #region Command line parsing
            statsFile = args[0] + ".csv";

            string changeList = null;
            args.Where(x => x.StartsWith(CmdLineOptsNames.taint + ":"))
            .Iter(s => changeList = s.Split(':')[1]);

            args.Where(x => x.StartsWith(CmdLineOptsNames.dacMerged + ":"))
            .Iter(s => DacMerged = s.Split(':')[1]);

            args.Where(x => x.StartsWith(CmdLineOptsNames.depTainted + ":"))
            .Iter(s => DependencyTaint = s.Split(':')[1]);

            ConservativeTaint = changeList == null;

            DumpTaint        = args.Any(x => x.ToLower() == CmdLineOptsNames.dumpTaint.ToLower());
            DataOnly         = args.Any(x => x.ToLower() == CmdLineOptsNames.dataOnly.ToLower());
            BothDependencies = args.Any(x => x.ToLower() == CmdLineOptsNames.both.ToLower()) && !DataOnly;

            PrintStats = args.Any(x => x.ToLower() == CmdLineOptsNames.stats.ToLower() || x.StartsWith(CmdLineOptsNames.stats + ":"));
            args.Where(x => x.StartsWith(CmdLineOptsNames.stats + ":"))
            .Iter(s => statsFile = s.Split(':')[1]);

            SemanticDep = args.Any(x => x.Contains(CmdLineOptsNames.semanticDep));

            Refine = args.Any(x => x == CmdLineOptsNames.refine || x.StartsWith(CmdLineOptsNames.refine + ":"));
            args.Where(x => x.StartsWith(CmdLineOptsNames.refine + ":"))
            .Iter(s => StackBound = int.Parse(s.Split(':')[1]));

            args.Where(x => x.StartsWith(CmdLineOptsNames.timeout + ":"))
            .Iter(s => Timeout = int.Parse(s.Split(':')[1]));

            args.Where(x => x.StartsWith(CmdLineOptsNames.inlineDepthDependency + ":"))
            .Iter(s => InlineDepth = int.Parse(s.Split(':')[1]));

            CoarseDiff       = args.Any(x => x.Contains(CmdLineOptsNames.coarseDiff));
            UseSummariesOnly = args.Any(x => x.Contains(CmdLineOptsNames.summaries));

            SplitMapsWithAliasAnalysis = args.Any(x => x.StartsWith(CmdLineOptsNames.splitMapsWithAliasAnalysis));

            // refined must have pruned dependencies
            Prune = Refine || args.Any(x => x.ToLower() == CmdLineOptsNames.prune.ToLower());

            if (StackBound < 2)
            {
                throw new Exception("Argument k to /refine:k has to be > 1");
            }

            ReadSet = args.Any(x => x.ToLower() == CmdLineOptsNames.readSet.ToLower());

            noMinUnsatCore = args.Any(x => x.ToLower() == CmdLineOptsNames.noMinUnsatCore.ToLower());

            AbstractNonTainted = args.Any(x => x.ToLower() == CmdLineOptsNames.abstractNonTainted.ToLower());

            AnnotateDependencies = args.Any(x => x.ToLower() == CmdLineOptsNames.annotateDependencies.ToLower());

            StripValueIs = args.Any(x => x.ToLower() == CmdLineOptsNames.stripValueIs.ToLower());

            RefinedStmtTaintAnalysis = args.Any(x => x.ToLower() == CmdLineOptsNames.refinedStmtTaintAnalysis.ToLower());

            if (args.Any(x => x.ToLower() == CmdLineOptsNames.debug.ToLower()))
            {
                Debugger.Launch();
            }
            #endregion


            var filename = args[0];
            if (!Utils.ParseProgram(filename, out program))
            {
                Usage();
                return(-1);
            }

            #region Cleanups

            Debug.Assert(program.Resolve() == 0 && program.Typecheck() == 0, "Initial program has errors.");
            //first thing is to prune based on callgraph, if receiving a change list
            if (changeList != null)
            {
                changeLog = PopulateChangeLog(changeList, program);
                HashSet <Procedure> changedProcs = new HashSet <Procedure>();
                foreach (var tuple  in changeLog)
                {
                    changedProcs.Add(program.FindProcedure(tuple.Item2));
                }
                //add an attribute to identify the changedProcs for later analysis
                changedProcs.Iter(p => p.AddAttribute("syntacticChangedProc", new string[] {}));
                program = new CallGraphBasedPruning(program, changedProcs).PruneProgram();
                Debug.Assert(program.Resolve() == 0 && program.Typecheck() == 0, "After Callgraph pruning the program has errors.");
            }
            //second thing is to remove Stubs
            program = new source.ProcessStubs(program).EliminateStubs();

            //cleanup assume value_is, as we are not printing a trace now
            //Dont cleanup value_is without this flag, SymDiff gets confused as it expects value_is for models
            if (StripValueIs)
            {
                (new Utils.RemoveValueIsAssumes()).Visit(program);
            }
            // create explicit variables for conditionals
            if (changeList != null) //only do this for taint analysis
            {
                if (!CoarseDiff)    //only do this if we're not using coarse diff, since otherwise it does not matter.
                {
                    (new Utils.AddExplicitConditionalVars()).Visit(program);
                }
            }
            //remove some HAVOC generated methods (should be in preprocess)
            //program.RemoveTopLevelDeclarations(x => (x is Procedure && ((Procedure)x).Name.Contains("HAVOC_memset")));
            //program.RemoveTopLevelDeclarations(x => (x is Implementation && ((Implementation)x).Name.Contains("HAVOC_memset")));
            //remove any forall axiom
            if (SplitMapsWithAliasAnalysis)
            {
                Console.WriteLine("Cleanup:Removing all background quantified axioms");
                program.RemoveTopLevelDeclarations(x => (x is Axiom && ((Axiom)x).Expr is ForallExpr));
                //rewrite map update M := M [x := y] --> M[x] := y
                (new Utils.RewriteSingletonMapUdates()).Visit(program);
            }
            #endregion

            //inline before proceeding
            if (InlineDepth > 0)
            {
                new DependencyInliner(program, InlineDepth).InlineImplementations();

                Utils.PrintProgram(program, "__after_inlining.bpl");
                Utils.ParseProgram("__after_inlining.bpl", out program);
            }

            if (SplitMapsWithAliasAnalysis)
            {
                var s = new SplitHeapUsingAliasAnalysis(program, filename);
                program = s.Run(); //the program is overwritten, no more use of
                return(0);
            }

            CallGraphHelper.WriteCallGraph(filename + ".cg", CallGraphHelper.ComputeCallGraph(program));
            Dictionary <string, HashSet <int> > sourceLines = new Dictionary <string, HashSet <int> >();
            program.Implementations.Iter(i => i.Blocks.Iter(b =>
            {
                var sourceFile = Utils.AttributeUtils.GetSourceFile(b);
                if (sourceFile != null)
                {
                    if (!sourceLines.ContainsKey(sourceFile))
                    {
                        sourceLines[sourceFile] = new HashSet <int>();
                    }
                    Utils.AttributeUtils.GetSourceLines(b).Iter(x => sourceLines[sourceFile].Add(x));
                }
            }));

            // remove redundant cmds
            //program.Implementations.Iter(i => i.Blocks.Iter(b => b.Cmds.RemoveAll(c => c is AssertCmd)));

            Analysis.DacSimplifier = new DacBasedSimplification(program, null);
            if (DacMerged != null)
            {
                Program mergedProgram;
                Utils.ParseProgram(DacMerged, out mergedProgram);
                Analysis.DacSimplifier = new DacBasedSimplification(program, mergedProgram);
                if (mergedProgram == null)
                {
                    Console.WriteLine("[Error] Merged file not found: {0}", DacMerged);
                    Environment.Exit(-1);
                }
                mergedProgram.Resolve();
                mergedProgram.Typecheck();
                DacSimplifier.Start();
            }


            RunAnalysis(filename, program);


            #region Display and Log

            DumpTaintedLinesToCsv(taintLog, string.IsNullOrEmpty(DacMerged) ? "tainted.csv" : "tainted.dac.csv");

            Utils.DisplayHtmlHelper displayHtml;
            if (DependencyTaint != null)
            {
                List <Tuple <string, string, int> > dependencyTaintedLines = Utils.StatisticsHelper.ReadCSVOutput(DependencyTaint);
                displayHtml = new Utils.DisplayHtmlHelper(changeLog, taintLog, dependenciesLog, taintedModSetLog, dependencyTaintedLines);
            }
            else
            {
                displayHtml = new Utils.DisplayHtmlHelper(changeLog, taintLog, dependenciesLog, taintedModSetLog);
            }
            displayHtml.GenerateHtmlOutput();

            if (PrintStats)
            {
                Utils.StatisticsHelper.GenerateCSVOutput(statsFile, statsLog);
                Console.WriteLine("Statistics generated in " + statsFile);
            }

            if (DumpTaint)
            {
                Utils.StatisticsHelper.GenerateCSVOutput(args[0] + ".taint", taintLog);
            }

            Dictionary <string, HashSet <int> > oldSourceLines = new Dictionary <string, HashSet <int> >(sourceLines);
            sourceLines.Clear();
            program.Implementations.Iter(i => i.Blocks.Iter(b =>
            {
                var sourceFile = Utils.AttributeUtils.GetSourceFile(b);
                if (sourceFile != null)
                {
                    if (!sourceLines.ContainsKey(sourceFile))
                    {
                        sourceLines[sourceFile] = new HashSet <int>();
                    }
                    //sourceLines[sourceFile].Add(Utils.AttributeUtils.GetSourceLine(b));
                    Utils.AttributeUtils.GetSourceLines(b).Iter(x => sourceLines[sourceFile].Add(x));
                }
            }));
            if (changeList != null)
            {
                // print number of tainted lines
                var taintedLines = new HashSet <Tuple <string, int> >(taintLog.Select(x => new Tuple <string, int>(x.Item1, x.Item3)));
                Console.WriteLine("#Orig lines, #Tainted lines, #Lines after abstractNonTainted: {0}, {1}, {2}",
                                  oldSourceLines.Sum(fl => fl.Value.Count),
                                  taintedLines.Count(),
                                  sourceLines.Sum(fl => fl.Value.Count));
                if (taintedLines.Count() == 0)
                {
                    Utils.PrintError("WARNING: Result may be inaccurate as the #tainted lines is 0");
                }
            }
            #endregion
            sw.Stop();
            return(0);
        }
Beispiel #14
0
 // map -> table
 public void Marshall()
 {
     table = new List <Tuple <string, string, string> >();
     map.Iter(tup => table.Add(tup));
 }
Beispiel #15
0
        // Replace "assume x == NULL" with "assume x == NULL; assert false;"
        // provided x can indeed alias NULL
        // Also returns a map from allocation_site to possible branches affected by it
        public static Tuple <Program, Dictionary <int, HashSet <int> > > Run(Program program, string ep, bool useAA, bool injectAssert)
        {
            var ib = new InstrumentBranches(program, useAA, injectAssert);

            ib.instrument(ep);

            if (!useAA)
            {
                Console.WriteLine("For deadcode detection, we added {0} angelic assertions", ib.assertsAdded);
                return(Tuple.Create <Program, Dictionary <int, HashSet <int> > >(program, null));
            }

            var inp = new PersistentProgram(program, ep, 1);
            //inp.writeToFile("progbefore.bpl");

            // Make sure that aliasing queries are on identifiers only
            var af =
                AliasAnalysis.SimplifyAliasingQueries.Simplify(program);

            // Do SSA
            program =
                SSA.Compute(program, PhiFunctionEncoding.Verifiable, new HashSet <string> {
                "int"
            });

            //BoogieUtil.PrintProgram(program, "b3.bpl");

            // Run AA
            AliasAnalysis.AliasAnalysisResults res =
                AliasAnalysis.AliasAnalysis.DoAliasAnalysis(program);

            // allocation site of null
            var nil = res.allocationSites[ib.nullQuery.Name].FirstOrDefault();

            Debug.Assert(nil != null);

            var deadcodeAssertId = 0;

            // add the assert false OR assume reach(true)
            var MkAssertFalse = new Func <int, PredicateCmd>(i =>
            {
                var acmd = injectAssert ? BoogieAstFactory.MkAssert(Expr.False) as PredicateCmd :
                           new AssumeCmd(Token.NoToken,
                                         new NAryExpr(Token.NoToken, new FunctionCall(ib.reach), new List <Expr> {
                    Expr.True
                })) as PredicateCmd;

                acmd.Attributes = new QKeyValue(Token.NoToken,
                                                "deadcode", new List <object> {
                    Expr.Literal(i)
                }, null);

                return(acmd);
            });

            // build a map from AA allocation sites to allocation_site id
            var as2id = new Dictionary <string, HashSet <int> >();

            foreach (var tup in ib.allocationSite2Func)
            {
                var asites = res.allocationSites[tup.Value.Name];
                asites.Where(s => !as2id.ContainsKey(s)).Iter(s => as2id.Add(s, new HashSet <int>()));
                asites.Iter(s => as2id[s].Add(tup.Key));
            }

            if (AliasAnalysis.AliasConstraintSolver.environmentPointersUnroll != 0)
            {
                Console.WriteLine("AA Warning: EnvironmentPointersUnroll is non-zero, which means that the dependency information for deadcode branches is not sound.");
                Console.WriteLine("AA Warning: We currently rely on: forall unknown allocation sites that return a, ReachableAllocationSitesViaFields(a) = {a}.");
            }

            // map from allocation_site to possible branches affected by it
            var depInfo = new Dictionary <int, HashSet <int> >();

            program = inp.getProgram();
            var id = 0; var added = 0;

            foreach (var impl in program.TopLevelDeclarations.OfType <Implementation>())
            {
                foreach (var blk in impl.Blocks)
                {
                    blk.Cmds.RemoveAll(c => (c is AssumeCmd) && QKeyValue.FindBoolAttribute((c as AssumeCmd).Attributes, "ForDeadCodeDetection"));

                    var ncmds = new List <Cmd>();
                    for (int i = 0; i < blk.Cmds.Count; i++)
                    {
                        ncmds.Add(blk.Cmds[i]);
                        var acmd = blk.Cmds[i] as AssumeCmd;
                        if (acmd == null)
                        {
                            continue;
                        }

                        id++;
                        if (!ib.id2Func.ContainsKey(id))
                        {
                            continue;
                        }

                        var asites = res.allocationSites[ib.id2Func[id].Name];
                        //if (!Options.disbleDeadcodeOpt || !asites.Contains(nil) && asites.Count != 0)
                        {
                            var assertid = deadcodeAssertId++;
                            ncmds.Add(MkAssertFalse(assertid));

                            // compute dependent allocations for this branch
                            var dep = new HashSet <int>();
                            asites.Where(a => as2id.ContainsKey(a))
                            .Iter(a => dep.UnionWith(as2id[a]));

                            dep.Where(d => !depInfo.ContainsKey(d))
                            .Iter(d => depInfo.Add(d, new HashSet <int>()));

                            dep.Iter(d => depInfo[d].Add(assertid));

                            added++;
                        }
                        //i++;
                    }
                    blk.Cmds = ncmds;
                }
            }
            //BoogieUtil.PrintProgram(program, "progafter.bpl");

            Console.WriteLine("For deadcode detection, we added {0} angelic assertions", added);
            return(Tuple.Create(program, depInfo));
        }
Beispiel #16
0
        private VCGenOutcome LearnInv(Dictionary<string, int> impl2Priority)
        {
            var worklist = new SortedSet<Tuple<int, string>>();
            name2Impl.Keys.Iter(k => worklist.Add(Tuple.Create(impl2Priority[k], k)));
            
            while (worklist.Any())
            {
                var impl = worklist.First().Item2;
                worklist.Remove(worklist.First());

                #region vcgen

                var gen = prover.VCExprGen;
                var terms = new List<Expr>();
                foreach (var tup in impl2FuncCalls[impl])
                {
                    var controlVar = tup.Item2;
                    var exprVars = tup.Item3;
                    var varList = new List<Expr>();
                    exprVars.Args.OfType<Expr>().Iter(v => varList.Add(v));

                    var args = new List<Expr>();
                    controlVar.InParams.Iter(v => args.Add(Expr.Ident(v)));
                    Expr term = Expr.Eq(new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args),
                                 function2Value[tup.Item1].Gamma(varList));

                    if (controlVar.InParams.Count != 0)
                    {
                        term = new ForallExpr(Token.NoToken, new List<Variable>(controlVar.InParams.ToArray()),
                            new Trigger(Token.NoToken, true, new List<Expr> { new NAryExpr(Token.NoToken, new FunctionCall(controlVar), args) }),
                            term);
                    }
                    terms.Add(term);

                    /*
                    foreach (var variable in varList)
                    {
                        terms.Add(Expr.Le(variable, Expr.Literal(10)));
                        terms.Add(Expr.Ge(variable, Expr.Literal(-10)));
                    }
                    */
                }
                var env = BinaryTreeAnd(terms, 0, terms.Count - 1);

                env.Typecheck(new TypecheckingContext((IErrorSink)null));
                var envVC = prover.Context.BoogieExprTranslator.Translate(env);
                var vc = gen.Implies(envVC, impl2VC[impl]);

                if (CommandLineOptions.Clo.Trace)
                {
                    Console.WriteLine("Verifying {0}: ", impl);
                    //Console.WriteLine("env: {0}", envVC);
                    var envFuncs = new HashSet<string>();
                    impl2FuncCalls[impl].Iter(tup => envFuncs.Add(tup.Item1));
                    envFuncs.Iter(f => PrintFunction(existentialFunctions[f]));
                }

                #endregion vcgen

                VCExpr finalVC;
                for (int i = 0; i <= bounds4cex.Count(); i++)
                {
#region boundcexvalues
                    /* Last iteration is when there are enforced no bounds on the cex values. */
                    if (i < bounds4cex.Count())
                    {
                        int bound = bounds4cex.ElementAt(i);
                        terms.Clear();
                        foreach (var tup in impl2FuncCalls[impl])
                        {
                            var exprVars = tup.Item3;
                            var varList = new List<Expr>();
                            exprVars.Args.OfType<Expr>().Where(v => v.Type.IsInt).Iter(v => varList.Add(v));
                            foreach (var variable in varList)
                            {
                                terms.Add(Expr.Le(variable, Expr.Literal(bound)));
                                terms.Add(Expr.Ge(variable, Expr.Literal(-1 * bound)));
                                //terms.Add(Expr.Ge(variable, Expr.Literal(0)));
                            }
                        }
                        var boundcex = BinaryTreeAnd(terms, 0, terms.Count - 1);
                        boundcex.Typecheck(new TypecheckingContext((IErrorSink)null));
                        var boundcexVC = prover.Context.BoogieExprTranslator.Translate(boundcex);

                        finalVC = gen.Implies(boundcexVC, vc);
                    }
                    else
                    {
                        //finalVC = vc;
                        
                        
                        int bound = 1000000;
                        terms.Clear();
                        foreach (var tup in impl2FuncCalls[impl])
                        {
                            var exprVars = tup.Item3;
                            var varList = new List<Expr>();
                            exprVars.Args.OfType<Expr>().Where(v => v.Type.IsInt).Iter(v => varList.Add(v));
                            foreach (var variable in varList)
                            {
                                terms.Add(Expr.Le(variable, Expr.Literal(bound)));
                                terms.Add(Expr.Ge(variable, Expr.Literal(-1 * bound)));
                                //terms.Add(Expr.Ge(variable, Expr.Literal(0)));
                            }
                        }
                        var boundcex = BinaryTreeAnd(terms, 0, terms.Count - 1);
                        boundcex.Typecheck(new TypecheckingContext((IErrorSink)null));
                        var boundcexVC = prover.Context.BoogieExprTranslator.Translate(boundcex);

                        finalVC = gen.Implies(boundcexVC, vc);
                         
                    }
#endregion boundcexvalues

                    var handler = impl2ErrorHandler[impl].Item1;
                    var collector = impl2ErrorHandler[impl].Item2;
                    collector.Reset(impl);
                    implicationCounterExamples.Clear();
                    VCisValid = true;   // set to false if control reaches HandleCounterExample
                    //realErrorEncountered = false;
                    //newSamplesAdded = false;
                    //this.posNegCexAdded = false;

                    var start = DateTime.Now;

                    prover.Push();
                    prover.Assert(gen.Not(finalVC), true);
                    prover.FlushAxiomsToTheoremProver();
                    prover.Check();
                    ProverInterface.Outcome proverOutcome = prover.CheckOutcomeCore(handler);

                    var inc = (DateTime.Now - start);
                    proverTime += inc;
                    numProverQueries++;

                    if (CommandLineOptions.Clo.Trace)
                        Console.WriteLine("Prover Time taken = " + inc.TotalSeconds.ToString());

                    if (proverOutcome == ProverInterface.Outcome.TimeOut || proverOutcome == ProverInterface.Outcome.OutOfMemory)
                    {
                        Console.WriteLine("Z3 Prover for implementation {0} times out or runs out of memory !", impl);
                        return new VCGenOutcome(proverOutcome, new List<Counterexample>());
                    }

                    if (!VCisValid)
                    {
                        /* There was a counterexample found and acted upon while proving the method. */
                        if (collector.real_errors.Count > 0)
                        {
                            return new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.real_errors);
                        }

                        if (collector.conjecture_errors.Count == 0)
                        {
                            // No positive or negative counter-example added. Need to add implication counter-examples
                            Debug.Assert(collector.implication_errors.Count > 0);
                            foreach (var cex in implicationCounterExamples)
                            {
                                AddCounterExample(cex);
                            }
                        }

                        //Debug.Assert(newSamplesAdded);
                        HashSet<string> funcsChanged;

                        if (!learn(out funcsChanged))
                        {
                            // learner timed out, ran into some errors, or if there is no consistent conjecture
                            prover.Pop();
                            if(collector.conjecture_errors.Count > 0)
                                return new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.conjecture_errors);
                            else
                                return new VCGenOutcome(ProverInterface.Outcome.Invalid, collector.implication_errors);
                        }
                        // propagate dependent guys back into the worklist, including self
                        var deps = new HashSet<string>();
                        deps.Add(impl);
                        funcsChanged.Iter(f => deps.UnionWith(function2implAssumed[f]));
                        funcsChanged.Iter(f => deps.UnionWith(function2implAsserted[f]));

                        deps.Iter(s => worklist.Add(Tuple.Create(impl2Priority[s], s)));

                        // break out of the loop that iterates over various bounds.
                        prover.Pop();
                        break;
                    }
                    else
                    {
                        prover.Pop();
                    }
                }
            }
            // The program was verified
            return new VCGenOutcome(ProverInterface.Outcome.Valid, new List<Counterexample>());            
        }
Beispiel #17
0
        // MAXSAT
        public void Explain(ProverInterface proverInterface,
                            Dictionary <Variable, bool> assignment, Variable refutedConstant)
        {
            Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);

            collector.examples.Clear();

            // debugging
            houdiniAssertConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
            houdiniAssumeConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
            Contract.Assert(assignment.ContainsKey(refutedConstant));
            Contract.Assert(houdiniAssertConstants.Contains(refutedConstant));

            var hardAssumptions = new List <VCExpr>();
            var softAssumptions = new List <VCExpr>();

            Boogie2VCExprTranslator exprTranslator = proverInterface.Context.BoogieExprTranslator;
            VCExpressionGenerator   exprGen        = proverInterface.VCExprGen;
            var controlExpr = VCExpressionGenerator.True;

            foreach (var tup in assignment)
            {
                Variable  constant = tup.Key;
                VCExprVar exprVar  = exprTranslator.LookupVariable(constant);
                var       val      = tup.Value;

                if (houdiniAssumeConstants.Contains(constant))
                {
                    if (tup.Value)
                    {
                        hardAssumptions.Add(exprVar);
                    }
                    else
                    {
                        // Previously removed assumed candidates are the soft constraints
                        softAssumptions.Add(exprVar);
                    }
                }
                else if (houdiniAssertConstants.Contains(constant))
                {
                    if (constant == refutedConstant)
                    {
                        hardAssumptions.Add(exprVar);
                    }
                    else
                    {
                        hardAssumptions.Add(exprGen.Not(exprVar));
                    }
                }
                else
                {
                    if (tup.Value)
                    {
                        hardAssumptions.Add(exprVar);
                    }
                    else
                    {
                        hardAssumptions.Add(exprGen.Not(exprVar));
                    }
                }

                // For an asserted condition (c ==> \phi),
                // ExplainHoudini's extra control constants (c_pos, c_neg) are used as follows:
                //   (true, true): "assert \phi"
                //   (false, _): "assert false"
                //   (true, false): "assert true"
                if (constant != refutedConstant && constantToControl.ContainsKey(constant.Name))
                {
                    var posControl = constantToControl[constant.Name].Item1;
                    var negControl = constantToControl[constant.Name].Item2;

                    // Handle self-recursion
                    if (houdiniAssertConstants.Contains(constant) && houdiniAssumeConstants.Contains(constant))
                    {
                        // disable this assert
                        controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprGen.Not(exprTranslator.LookupVariable(negControl))));
                    }
                    else
                    {
                        // default values for control variables
                        controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprTranslator.LookupVariable(negControl)));
                    }
                }
            }

            hardAssumptions.Add(exprGen.Not(conjecture));

            // default values for control variables
            Contract.Assert(constantToControl.ContainsKey(refutedConstant.Name));
            var pc = constantToControl[refutedConstant.Name].Item1;
            var nc = constantToControl[refutedConstant.Name].Item2;

            var controlExprNoop = exprGen.And(controlExpr,
                                              exprGen.And(exprTranslator.LookupVariable(pc), exprTranslator.LookupVariable(nc)));

            var controlExprFalse = exprGen.And(controlExpr,
                                               exprGen.And(exprGen.Not(exprTranslator.LookupVariable(pc)), exprGen.Not(exprTranslator.LookupVariable(nc))));

            if (CommandLineOptions.Clo.Trace)
            {
                Console.WriteLine("Verifying (MaxSat) " + descriptiveName);
            }
            DateTime now = DateTime.UtcNow;

            var el = CommandLineOptions.Clo.ProverCCLimit;

            CommandLineOptions.Clo.ProverCCLimit = 1;

            var outcome = ProverInterface.Outcome.Undetermined;

            do
            {
                List <int> unsatisfiedSoftAssumptions;

                hardAssumptions.Add(controlExprNoop);
                outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions, out unsatisfiedSoftAssumptions, handler);
                hardAssumptions.RemoveAt(hardAssumptions.Count - 1);

                if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.OutOfResource || outcome == ProverInterface.Outcome.Undetermined)
                {
                    break;
                }

                var reason = new HashSet <string>();
                unsatisfiedSoftAssumptions.Iter(i => reason.Add(softAssumptions[i].ToString()));
                if (CommandLineOptions.Clo.Trace)
                {
                    Console.Write("Reason for removal of {0}: ", refutedConstant.Name);
                    reason.Iter(r => Console.Write("{0} ", r));
                    Console.WriteLine();
                }

                // Get rid of those constants from the "reason" that can even make
                // "assert false" pass

                hardAssumptions.Add(controlExprFalse);
                var softAssumptions2 = new List <VCExpr>();
                for (int i = 0; i < softAssumptions.Count; i++)
                {
                    if (unsatisfiedSoftAssumptions.Contains(i))
                    {
                        softAssumptions2.Add(softAssumptions[i]);
                        continue;
                    }
                    hardAssumptions.Add(softAssumptions[i]);
                }

                var unsatisfiedSoftAssumptions2 = new List <int>();
                outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2, out unsatisfiedSoftAssumptions2, handler);

                if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.OutOfResource || outcome == ProverInterface.Outcome.Undetermined)
                {
                    break;
                }

                unsatisfiedSoftAssumptions2.Iter(i => reason.Remove(softAssumptions2[i].ToString()));
                var reason1 = new HashSet <string>(); //these are the reasons for inconsistency
                unsatisfiedSoftAssumptions2.Iter(i => reason1.Add(softAssumptions2[i].ToString()));

                if (CommandLineOptions.Clo.Trace)
                {
                    Console.Write("Revised reason for removal of {0}: ", refutedConstant.Name);
                    reason.Iter(r => Console.Write("{0} ", r));
                    Console.WriteLine();
                }
                foreach (var r in reason)
                {
                    Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, r, descriptiveName);
                }
                //also add the removed reasons using dotted edges (requires- x != 0, requires- x == 0 ==> assert x != 0)
                foreach (var r in reason1)
                {
                    Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=blue style=dotted ];", refutedConstant.Name, r, descriptiveName);
                }
            } while (false);

            if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.OutOfResource || outcome == ProverInterface.Outcome.Undetermined)
            {
                Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, "TimeOut", descriptiveName);
            }

            CommandLineOptions.Clo.ProverCCLimit = el;

            double queryTime = (DateTime.UtcNow - now).TotalSeconds;

            stats.proverTime += queryTime;
            stats.numProverQueries++;
            if (CommandLineOptions.Clo.Trace)
            {
                Console.WriteLine("Time taken = " + queryTime);
            }
        }
Beispiel #18
0
        // MAXSAT
        public void Explain(ProverInterface proverInterface, 
            Dictionary<Variable, bool> assignment, Variable refutedConstant)
        {
            Contract.Assert(CommandLineOptions.Clo.ExplainHoudini);

            collector.examples.Clear();

            // debugging
            houdiniAssertConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
            houdiniAssumeConstants.Iter(v => System.Diagnostics.Debug.Assert(assignment.ContainsKey(v)));
            Contract.Assert(assignment.ContainsKey(refutedConstant));
            Contract.Assert(houdiniAssertConstants.Contains(refutedConstant));

            var hardAssumptions = new List<VCExpr>();
            var softAssumptions = new List<VCExpr>();

            Boogie2VCExprTranslator exprTranslator = proverInterface.Context.BoogieExprTranslator;
            VCExpressionGenerator exprGen = proverInterface.VCExprGen;
            var controlExpr = VCExpressionGenerator.True;

            foreach (var tup in assignment)
            {
            Variable constant = tup.Key;
            VCExprVar exprVar = exprTranslator.LookupVariable(constant);
            var val = tup.Value;

            if (houdiniAssumeConstants.Contains(constant))
            {
                if (tup.Value)
                    hardAssumptions.Add(exprVar);
                else
                    // Previously removed assumed candidates are the soft constraints
                    softAssumptions.Add(exprVar);
            }
            else if (houdiniAssertConstants.Contains(constant))
            {
                if (constant == refutedConstant)
                    hardAssumptions.Add(exprVar);
                else
                    hardAssumptions.Add(exprGen.Not(exprVar));
            }
            else
            {
                if (tup.Value)
                    hardAssumptions.Add(exprVar);
                else
                    hardAssumptions.Add(exprGen.Not(exprVar));
            }

            // For an asserted condition (c ==> \phi),
            // ExplainHoudini's extra control constants (c_pos, c_neg) are used as follows:
            //   (true, true): "assert \phi"
            //   (false, _): "assert false"
            //   (true, false): "assert true"
            if (constant != refutedConstant && constantToControl.ContainsKey(constant.Name))
            {
                var posControl = constantToControl[constant.Name].Item1;
                var negControl = constantToControl[constant.Name].Item2;

                // Handle self-recursion
                if (houdiniAssertConstants.Contains(constant) && houdiniAssumeConstants.Contains(constant))
                {
                    // disable this assert
                    controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprGen.Not(exprTranslator.LookupVariable(negControl))));
                }
                else
                {
                    // default values for control variables
                    controlExpr = exprGen.And(controlExpr, exprGen.And(exprTranslator.LookupVariable(posControl), exprTranslator.LookupVariable(negControl)));
                }
            }
            }

            hardAssumptions.Add(exprGen.Not(conjecture));

            // default values for control variables
            Contract.Assert(constantToControl.ContainsKey(refutedConstant.Name));
            var pc = constantToControl[refutedConstant.Name].Item1;
            var nc = constantToControl[refutedConstant.Name].Item2;

            var controlExprNoop = exprGen.And(controlExpr,
            exprGen.And(exprTranslator.LookupVariable(pc), exprTranslator.LookupVariable(nc)));

            var controlExprFalse = exprGen.And(controlExpr,
            exprGen.And(exprGen.Not(exprTranslator.LookupVariable(pc)), exprGen.Not(exprTranslator.LookupVariable(nc))));

            if (CommandLineOptions.Clo.Trace)
            {
            Console.WriteLine("Verifying (MaxSat) " + descriptiveName);
            }
            DateTime now = DateTime.UtcNow;

            var el = CommandLineOptions.Clo.ProverCCLimit;
            CommandLineOptions.Clo.ProverCCLimit = 1;

            var outcome = ProverInterface.Outcome.Undetermined;

            do
            {
            List<int> unsatisfiedSoftAssumptions;

            hardAssumptions.Add(controlExprNoop);
            outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions, out unsatisfiedSoftAssumptions, handler);
            hardAssumptions.RemoveAt(hardAssumptions.Count - 1);

            if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
                break;

            var reason = new HashSet<string>();
            unsatisfiedSoftAssumptions.Iter(i => reason.Add(softAssumptions[i].ToString()));
            if (CommandLineOptions.Clo.Trace)
            {
                Console.Write("Reason for removal of {0}: ", refutedConstant.Name);
                reason.Iter(r => Console.Write("{0} ", r));
                Console.WriteLine();
            }

            // Get rid of those constants from the "reason" that can even make
            // "assert false" pass

            hardAssumptions.Add(controlExprFalse);
            var softAssumptions2 = new List<VCExpr>();
            for (int i = 0; i < softAssumptions.Count; i++)
            {
                if (unsatisfiedSoftAssumptions.Contains(i))
                {
                    softAssumptions2.Add(softAssumptions[i]);
                    continue;
                }
                hardAssumptions.Add(softAssumptions[i]);
            }

            var unsatisfiedSoftAssumptions2 = new List<int>();
            outcome = proverInterface.CheckAssumptions(hardAssumptions, softAssumptions2, out unsatisfiedSoftAssumptions2, handler);

            if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
                break;

            unsatisfiedSoftAssumptions2.Iter(i => reason.Remove(softAssumptions2[i].ToString()));
            if (CommandLineOptions.Clo.Trace)
            {
                Console.Write("Revised reason for removal of {0}: ", refutedConstant.Name);
                reason.Iter(r => Console.Write("{0} ", r));
                Console.WriteLine();
            }
            foreach (var r in reason)
            {
                Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, r, descriptiveName);
            }
            } while (false);

            if (outcome == ProverInterface.Outcome.TimeOut || outcome == ProverInterface.Outcome.OutOfMemory || outcome == ProverInterface.Outcome.Undetermined)
            {
            Houdini.explainHoudiniDottyFile.WriteLine("{0} -> {1} [ label = \"{2}\" color=red ];", refutedConstant.Name, "TimeOut", descriptiveName);
            }

            CommandLineOptions.Clo.ProverCCLimit = el;

            double queryTime = (DateTime.UtcNow - now).TotalSeconds;
            stats.proverTime += queryTime;
            stats.numProverQueries++;
            if (CommandLineOptions.Clo.Trace)
            {
            Console.WriteLine("Time taken = " + queryTime);
            }
        }