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); }
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."); } }
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)); }
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; } }
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; }
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); }
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); } }
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); }
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); }
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); }
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); }
// map -> table public void Marshall() { table = new List <Tuple <string, string, string> >(); map.Iter(tup => table.Add(tup)); }
// 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)); }
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>()); }
// 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); } }
// 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); } }