bool IsAssumeNonNull(Cmd cmd) { var acmd = cmd as AssumeCmd; if (acmd == null) { return(false); } if (BoogieUtil.checkAttrExists("partition", acmd.Attributes)) { return(false); } var expr = acmd.Expr as NAryExpr; if (expr == null) { return(false); } var exprIsNull = new Predicate <Expr>(e => { return((e is IdentifierExpr) && (e as IdentifierExpr).Name == "null"); }); if (expr.Fun is BinaryOperator && (expr.Fun as BinaryOperator).Op == BinaryOperator.Opcode.Neq && (exprIsNull(expr.Args[0]) || exprIsNull(expr.Args[1]))) { return(true); } return(false); }
private void ChangeStubsIntoUnkowns() { var procsWithImpl = prog.TopLevelDeclarations.OfType <Implementation>() .Select(x => x.Proc); var procs = prog.TopLevelDeclarations.OfType <Procedure>(); // remove procedures that are never called var procsUsed = new HashSet <string>(); prog.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.cmds.OfType <CallCmd>() .Iter(cc => procsUsed.Add(cc.callee)))); //TODO: this can be almost quadratic in the size of |Procedures|, cleanup var procsWithoutImpl = procs.Where(x => !procsWithImpl.Contains(x) && procsUsed.Contains(x.Name)); var stubImpls = new List <Implementation>(); foreach (var p in procsWithoutImpl) { if (BoogieUtil.checkAttrExists("allocator", p.Attributes)) { continue; } MkStubImplementation(stubImpls, p); } prog.AddTopLevelDeclarations(stubImpls); }
void Instrument(Implementation impl) { var varDecls = new Dictionary <string, string>(); var cb = new CollectBasePointer(varDecls); cb.VisitImplementation(impl); foreach (var block in impl.Blocks) { var newcmds = new List <Cmd>(); foreach (Cmd cmd in block.Cmds) { if (cmd is AssumeCmd && BoogieUtil.checkAttrExists("nonnull", (cmd as AssumeCmd).Attributes)) { continue; } if (cmd is AssignCmd) { newcmds.AddRange(ProcessAssign(cmd as AssignCmd, varDecls)); } else if (cmd is AssumeCmd) { newcmds.AddRange(ProcessAssume(cmd as AssumeCmd, varDecls)); } else if (cmd is CallCmd) { newcmds.AddRange(ProcessCall(cmd as CallCmd, varDecls)); } else { newcmds.Add(cmd); } } block.Cmds = newcmds; } }
public override Expr VisitIdentifierExpr(IdentifierExpr node) { if (!Matches || _toConsume.Count == 0) { Matches = false; return(base.VisitIdentifierExpr(node)); } // check if we need to switch to anyExprMode if (_toConsume.Peek() is NAryExpr && (((NAryExpr)_toConsume.Peek()).Fun) is FunctionCall && BoogieUtil.checkAttrExists(BoogieKeyWords.AnyExpr, ((FunctionCall)((NAryExpr)_toConsume.Peek()).Fun).Func.Attributes)) { _anyExprMode = true; _toConsume.Pop(); ((NAryExpr)_toConsume.Peek()).Args.Iter(arg => _toConsume.Push(arg)); var result = VisitIdentifierExpr(node); _anyExprMode = false; return(result); } if (!(_toConsume.Peek() is IdentifierExpr)) { Matches = false; return(base.VisitIdentifierExpr(node)); } var idexToConsume = (IdentifierExpr)_toConsume.Peek(); if (idexToConsume.Decl != null) { if (Equals(node.Decl.TypedIdent.Type, idexToConsume.Decl.TypedIdent.Type) && AreAttributesASubset(idexToConsume.Decl.Attributes, node.Decl.Attributes)) { Substitution.Add(idexToConsume.Decl, node); _toConsume.Pop(); } else { Matches = false; } return(base.VisitIdentifierExpr(node)); } if (idexToConsume.Name == node.Name) { return(base.VisitIdentifierExpr(node)); } Matches = false; return(base.VisitIdentifierExpr(node)); }
public static bool checkFunctionsAreInlined(Program program) { foreach (var func in program.TopLevelDeclarations.OfType <Function>()) { if (func.Body != null && !BoogieUtil.checkAttrExists("inline", func.Attributes)) { Console.WriteLine("Function {0} does not have an inline attribute", func.Name); return(false); } } return(true); }
private static bool MatchParams(ref QKeyValue toMatchAnyParamsAttributes, ref int anyParamsPosition, Dictionary <Declaration, Expr> paramSubstitution, List <Variable> toMatchInParams, List <Variable> toMatchProcInParams, List <Variable> dwfInParams, List <Variable> dwfProcInParams, bool matchPtrs) { // match procedure parameters for (var i = 0; i < toMatchInParams.Count; i++) { if (i == toMatchInParams.Count - 1 && BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.AnyParams, toMatchProcInParams[i].Attributes)) { toMatchAnyParamsAttributes = toMatchInParams[i].Attributes; if (toMatchAnyParamsAttributes != null) { toMatchAnyParamsAttributes.Next = toMatchProcInParams[i].Attributes; } else { toMatchAnyParamsAttributes = toMatchProcInParams[i].Attributes; } toMatchAnyParamsAttributes = BoogieUtil.removeAttr(ExprMatchVisitor.BoogieKeyWords.AnyParams, toMatchAnyParamsAttributes); //TODO the type may also be constrained anyParamsPosition = i; //don't add it to the substitution continue; } // not anyParams and param counts don't match.. if (i >= dwfInParams.Count) { return(false); } // param types don't match if (!toMatchInParams[i].TypedIdent.Type.Equals(dwfInParams[i].TypedIdent.Type)) { return(false); } // if {:#MatchPtrs} attribute is present, check if pointer references match if (matchPtrs) { if (!MatchPtrs(toMatchProcInParams[i], dwfProcInParams[i])) { return(false); } } paramSubstitution.Add(toMatchInParams[i], new IdentifierExpr(Token.NoToken, dwfInParams[i])); } return(true); }
public override List <Cmd> VisitCmdSeq(List <Cmd> cmdSeq) { int callCmdCount = -1; var newCmdSeq = new List <Cmd>(); foreach (Cmd c in cmdSeq) { newCmdSeq.Add(c); var callCmd = c as CallCmd; if (callCmd != null) { callCmdCount++; } if (callCmd != null && BoogieUtil.checkAttrExists(AvnAnnotations.AngelicUnknownCall, callCmd.Proc.Attributes)) { var retCall = callCmd.Outs[0]; btype retType = callCmd.Proc.OutParams[0].TypedIdent.Type; if (retType == null) { retType = btype.Int; } var mallocTriggerFn = new Function(Token.NoToken, mallocTriggerFuncName + mallocTriggers.Count, new List <Variable>() { BoogieAstFactory.MkFormal("a", retType, false) }, BoogieAstFactory.MkFormal("r", btype.Bool, false)); mallocTriggers[callCmd] = mallocTriggerFn; var callId = QKeyValue.FindIntAttribute(callCmd.Attributes, cba.RestrictToTrace.ConcretizeCallIdAttr, -1); Debug.Assert(callId == -1, "Calls to unknown must not already be tagged with an ID"); callId = instance.id++; callCmd.Attributes = new QKeyValue(Token.NoToken, cba.RestrictToTrace.ConcretizeCallIdAttr, new List <object> { Expr.Literal(callId) }, callCmd.Attributes); instance.mallocTriggersLocation[callId] = mallocTriggerFn.Name; instance.mallocTriggerToAllocationSite[mallocTriggerFn.Name] = callId; instance.prog.AddTopLevelDeclaration(mallocTriggerFn); var fnApp = new NAryExpr(Token.NoToken, new FunctionCall(mallocTriggerFn), new List <Expr> () { retCall }); newCmdSeq.Add(BoogieAstFactory.MkAssume(fnApp)); } } return(base.VisitCmdSeq(newCmdSeq)); }
public override Implementation VisitImplementation(Implementation node) { var varDecls = new Dictionary <string, string>(); var cb = new CollectBasePointer(varDecls); cb.VisitImplementation(node); foreach (var b in node.Blocks) { var newCmds = new List <Cmd>(); foreach (var c in b.Cmds) { if (c is AssumeCmd) { var asmCmd = c as AssumeCmd; if (BoogieUtil.checkAttrExists("nonnull", asmCmd.Attributes)) { var expr = asmCmd.Expr as NAryExpr; expr.Args[1] = nil; newCmds.Add(c); continue; } } if (c is AssignCmd) { var asnCmd = c as AssignCmd; var reads = new GatherMemAccesses(); asnCmd.Rhss.Iter(e => reads.VisitExpr(e)); foreach (var tup in reads.accesses) { var ptr = tup.Item2; string basePtr; if (varDecls.TryGetValue(ptr.ToString(), out basePtr)) { newCmds.Add(MkAssume(Expr.Ident(BoogieAstFactory.MkFormal(basePtr, btype.Int, true)))); } else { newCmds.Add(MkAssume(ptr)); } } } newCmds.Add(c); } b.cmds = newCmds; } return(node); }
public override Expr VisitLiteralExpr(LiteralExpr node) { if (!Matches || _toConsume.Count == 0) { Matches = false; return(base.VisitLiteralExpr(node)); } // check if we need to switch to anyExprMode if (_toConsume.Peek() is NAryExpr && (((NAryExpr)_toConsume.Peek()).Fun) is FunctionCall && ((FunctionCall)((NAryExpr)_toConsume.Peek()).Fun).Func != null && BoogieUtil.checkAttrExists(BoogieKeyWords.AnyExpr, ((FunctionCall)((NAryExpr)_toConsume.Peek()).Fun).Func.Attributes)) { _anyExprMode = true; _toConsume.Pop(); ((NAryExpr)_toConsume.Peek()).Args.Iter(arg => _toConsume.Push(arg)); var result = VisitLiteralExpr(node); _anyExprMode = false; return(result); } if (!(_toConsume.Peek() is LiteralExpr)) { if (_toConsume.Peek() is IdentifierExpr && ((IdentifierExpr)_toConsume.Peek()).Decl != null && !BoogieUtil.checkAttrExists(BoogieKeyWords.IdExpr, ((IdentifierExpr)_toConsume.Peek()).Decl.Attributes)) { Substitution.Add(((IdentifierExpr)_toConsume.Peek()).Decl, node); _toConsume.Pop(); return(node); } Matches = false; return(base.VisitLiteralExpr(node)); } if (node.Val.Equals(((LiteralExpr)_toConsume.Peek()).Val)) { return(base.VisitLiteralExpr(node)); } Matches = false; return(base.VisitLiteralExpr(node)); }
public static bool AreAttributesASubset(QKeyValue left, QKeyValue right) { for (; left != null; left = left.Next) //TODO: make a reference copy of left to work on?? { //need to filter out keyword attributes if (BoogieKeyWords.AllKeywords.Contains(left.Key)) { continue; } if (!BoogieUtil.checkAttrExists(left.Key, right)) { return(false); } } return(true); }
private static Procedure FindMalloc(Program prog) { Procedure mallocProcedureFull = null; //find the malloc and malloc-full procedures foreach (var proc in prog.TopLevelDeclarations.OfType <Procedure>() .Where(p => BoogieUtil.checkAttrExists("allocator", p.Attributes))) { var attr = QKeyValue.FindStringAttribute(proc.Attributes, "allocator"); if (attr == "full") { mallocProcedureFull = proc; } } return(mallocProcedureFull); }
private void ChangeStubsIntoUnkowns() { var procsWithImpl = prog.TopLevelDeclarations.OfType <Implementation>() .Select(x => x.Proc); var procs = prog.TopLevelDeclarations.OfType <Procedure>(); //TODO: this can be almost quadratic in the size of |Procedures|, cleanup var procsWithoutImpl = procs.Where(x => !procsWithImpl.Contains(x)); var stubImpls = new List <Implementation>(); foreach (var p in procsWithoutImpl) { if (BoogieUtil.checkAttrExists("allocator", p.Attributes)) { continue; } MkStubImplementation(stubImpls, p); } prog.AddTopLevelDeclarations(stubImpls); }
// locate HAVOC_MALLOC private static Procedure FindMalloc(Program prog) { Procedure mallocProc = null; //find the malloc and malloc-full procedures foreach (var proc in prog.TopLevelDeclarations.OfType <Procedure>() .Where(p => BoogieUtil.checkAttrExists("allocator", p.Attributes))) { var attr = QKeyValue.FindStringAttribute(proc.Attributes, "allocator"); if (attr == null) { mallocProc = proc; } } if (mallocProc == null) { throw new Exception("ABORT: no malloc procedure with {:allocator} declared in the input program"); } return(mallocProc); }
public override CBAProgram runCBAPass(CBAProgram p) { p.Typecheck(); p.TopLevelDeclarations.OfType <Procedure>().Iter(proc => procsWithoutBody.Add(proc.Name)); p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => procsWithoutBody.Remove(impl.Name)); // remove malloc //procsWithoutBody.RemoveWhere(str => str.Contains("malloc")); // Make sure that procs without a body don't modify globals foreach (var proc in p.TopLevelDeclarations.OfType <Procedure>().Where(proc => procsWithoutBody.Contains(proc.Name))) { if (proc.Modifies.Count > 0 && !BoogieUtil.checkAttrExists("allocator", proc.Attributes)) { throw new InvalidInput("Produce Bug Witness: Procedure " + proc.Name + " modifies globals"); } } // Add the boogie_si_record_int procedure var inpVarInt = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Int), true); var inpVarBool = new Formal(Token.NoToken, new TypedIdent(Token.NoToken, "x", Microsoft.Boogie.Type.Bool), true); var reProcInt = new Procedure(Token.NoToken, recordProcNameInt, new List <TypeVariable>(), new List <Variable> { inpVarInt }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); var reProcBool = new Procedure(Token.NoToken, recordProcNameBool, new List <TypeVariable>(), new List <Variable> { inpVarBool }, new List <Variable>(), new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); // Add procedures for initialization of local variables foreach (var impl in p.TopLevelDeclarations.OfType <Implementation>()) { var ncmds = new List <Cmd>(); foreach (var loc in (impl.LocVars.Concat(impl.OutParams))) { var cc = new CallCmd(Token.NoToken, GetInitLocalsProc(loc.TypedIdent.Type).Name, new List <Expr>(), new List <IdentifierExpr>(new IdentifierExpr[] { Expr.Ident(loc) })); cc.Attributes = new QKeyValue(Token.NoToken, RestrictToTrace.ConcretizeConstantNameAttr, new List <object> { LocalVarInitValueAttr }, cc.Attributes); cc.Proc = GetInitLocalsProc(loc.TypedIdent.Type); ncmds.Add(cc); } ncmds.AddRange(impl.Blocks[0].Cmds); impl.Blocks[0].Cmds = ncmds; } typeToInitLocalsProc.Values.Iter(pr => procsWithoutBody.Add(pr.Name)); typeToInitLocalsProc.Values.Iter(pr => p.AddTopLevelDeclaration(pr)); // save the current program var fd = new FixedDuplicator(true); var modInpProg = fd.VisitProgram(p); // Instrument to record stuff p.TopLevelDeclarations.OfType <Implementation>().Iter(impl => impl.Blocks.Iter(b => instrument(b))); // Name clash if this assert fails Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameInt) == null); Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, recordProcNameBool) == null); foreach (var rp in typeToRecordProc.Values) { Debug.Assert(BoogieUtil.findProcedureDecl(p.TopLevelDeclarations, rp.Name) == null); } p.AddTopLevelDeclaration(reProcInt); p.AddTopLevelDeclaration(reProcBool); p.AddTopLevelDeclarations(typeToRecordProc.Values); var tmainimpl = BoogieUtil.findProcedureImpl(p.TopLevelDeclarations, p.mainProcName); if (!QKeyValue.FindBoolAttribute(tmainimpl.Attributes, "entrypoint")) { tmainimpl.AddAttribute("entrypoint"); } var program = new PersistentCBAProgram(p, p.mainProcName, 0); //program.writeToFile("beforeverify.bpl"); var vp = new VerificationPass(true); vp.run(program); success = vp.success; if (success) { return(null); } var trace = mapBackTraceRecord(vp.trace); RestrictToTrace.addConcretization = true; RestrictToTrace.addConcretizationAsConstants = true; var tinfo = new InsertionTrans(); var rt = new RestrictToTrace(modInpProg, tinfo); rt.addTrace(trace); RestrictToTrace.addConcretization = false; RestrictToTrace.addConcretizationAsConstants = false; var rtprog = rt.getProgram(); // Build a map of where the alloc constants are from allocConstants = rt.concretizeConstantToCall; // Add symbolic constants for angelic map havocs var newDecls = new List <Constant>(); rtprog.TopLevelDeclarations.OfType <Implementation>().Iter(impl => impl.Blocks.Iter(b => instrumentMapHavocs(b, allocConstants, newDecls))); rtprog.AddTopLevelDeclarations(newDecls); /* * foreach (var impl in rtprog.TopLevelDeclarations.OfType<Implementation>()) * { * // strip _trace from the impl name * var implName = impl.Name; * var c = implName.LastIndexOf("_trace"); * while (c != -1) * { * implName = implName.Substring(0, c); * c = implName.LastIndexOf("_trace"); * } * * var vu = new VarsUsed(); * vu.VisitImplementation(impl); * vu.varsUsed.Where(s => s.StartsWith("alloc_")) * .Iter(s => allocConstants[s] = implName); * } */ BoogieUtil.findProcedureImpl(rtprog.TopLevelDeclarations, rt.getFirstNameInstance(p.mainProcName)) .AddAttribute("entrypoint"); program = new PersistentCBAProgram(rtprog, rt.getFirstNameInstance(p.mainProcName), p.contextBound); // Lets inline it all var inlp = new InliningPass(1); program = inlp.run(program); var compress = new CompressBlocks(); var ret = program.getProgram(); compress.VisitProgram(ret); return(new CBAProgram(ret, program.mainProcName, 0)); }
static Program GetProgram(string filename) { var init = GetInputProgram(filename); if (Options.addInitialization) { ComputeandInitializeUninitializedLocals(init); } // Do some instrumentation for the input program if (Options.markAssumesAsSlic) { // Mark all assumes as "slic" var AddAnnotation = new Action <AssumeCmd>(ac => { ac.Attributes = new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes); }); init.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.Cmds.OfType <AssumeCmd>() .Iter(AddAnnotation))); } // Only keep assertions in assertProc procedures if (Options.assertProcs != null) { (new Instrumentations.PruneNonAssertProcs(Options.assertProcs)).Visit(init); } // Inline procedures supplied with {:inline} annotation cba.Driver.InlineProcedures(init); // Remove {:inline} impls init.RemoveTopLevelDeclarations(decl => (decl is Implementation) && (BoogieUtil.checkAttrExists("inline", decl.Attributes) || BoogieUtil.checkAttrExists("inline", (decl as Implementation).Proc.Attributes))); // Restrict entrypoints to those provided explicitly (overrides any other way to providing entryPoints) if (Options.entryPointProcs != null) { //only consider the user provided entry points in command line Options.useHarnessTag = false; Options.useProvidedEntryPoints = true; init.TopLevelDeclarations.OfType <NamedDeclaration>() .Iter(d => d.Attributes = BoogieUtil.removeAttr("entrypoint", d.Attributes)); } var matchesEntryPointExclude = new Func <string, bool>(s => { return(Options.entryPointExcludes.Any(t => new System.Text.RegularExpressions.Regex(t).IsMatch(s))); }); //when both entryPointProcs == null and entryPointExcludes == null, it should not add any entrypointProcs if (Options.entryPointProcs != null || Options.entryPointExcludes != null) { init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => d is Procedure || d is Implementation) .Where(d => Options.entryPointProcs == null || Options.entryPointProcs.Contains(d.Name)) .Where(d => (Options.entryPointExcludes == null || !matchesEntryPointExclude(d.Name))) .Iter(d => d.AddAttribute("entrypoint")); } // Add {:entrypoint} to procs with {:harness} if (Options.useHarnessTag) { foreach (var decl in init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => QKeyValue.FindBoolAttribute(d.Attributes, "harness"))) { decl.AddAttribute("entrypoint"); } } // inlining introduces havoc statements; lets just delete them (TODO: make inlining not introduce redundant havoc statements) //foreach (var impl in init.TopLevelDeclarations.OfType<Implementation>()) //{ // impl.Blocks.Iter(blk => // blk.Cmds.RemoveAll(cmd => cmd is HavocCmd)); //} ReplaceHavocsWithNonDet(init); //Instrument to create the harness harnessInstrumentation = new Instrumentations.HarnessInstrumentation(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.useProvidedEntryPoints); harnessInstrumentation.DoInstrument(); //resolve+typecheck wo bothering about modSets CommandLineOptions.Clo.DoModSetAnalysis = true; init = BoogieUtil.ReResolveInMem(init); CommandLineOptions.Clo.DoModSetAnalysis = false; // Update mod sets BoogieUtil.DoModSetAnalysis(init); if (Options.AddMapSelectNonNullAssumptions) { (new Instrumentations.AssertMapSelectsNonNull()).Visit(init); } BoogieUtil.pruneProcs(init, AvnAnnotations.CORRAL_MAIN_PROC); if (Options.deadCodeDetect) { // Tag branches as reachable var tup = InstrumentBranches.Run(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.UseAliasAnalysisForAngelicAssertions, false); init = tup.Item1; // TODO: inject this information into the program itself DeadCodeBranchesDependencyInfo = tup.Item2; } return(init); }
public override Block VisitBlock(Block node) { List <Cmd> newCmds = new List <Cmd>(); foreach (Cmd cmd in node.Cmds) { if (cmd is AssumeCmd) { if (!(cmd as AssumeCmd).Expr.ToString().Equals(Expr.False.ToString())) { newCmds.Add(VisitAssumeCmd(cmd as AssumeCmd)); } else { //node.TransferCmd = new ReturnCmd(Token.NoToken); // create a stub //newCmds.Add(cmd); // we want to add a call to a stub procedure in case AA decides that the function pointer never gets any address // we need to create three types of stub procedures: // 1) no returning value (actually just let it return) // 2) returning a pointer // 3) returning a scalar if (currProc.OutParams.Count > 0) { Variable procRet = currProc.OutParams[0]; if (BoogieUtil.checkAttrExists("scalar", procRet.Attributes)) { if (specialScalarFunc == null) { // make a procedure specialScalarFunc = new Procedure(Token.NoToken, "$devirtbounce_special_scalar", new List <TypeVariable>(), new List <Variable>(), currProc.OutParams, new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); } CallCmd callCmd = new CallCmd(Token.NoToken, specialScalarFunc.Name, new List <Expr>(), new List <IdentifierExpr>() { Expr.Ident(procRet) }); newCmds.Add(callCmd); } else { if (specialPtrFunc == null) { // make a procedure specialPtrFunc = new Procedure(Token.NoToken, "$devirtbounce_special_pointer", new List <TypeVariable>(), new List <Variable>(), currProc.OutParams, new List <Requires>(), new List <IdentifierExpr>(), new List <Ensures>()); } CallCmd callCmd = new CallCmd(Token.NoToken, specialPtrFunc.Name, new List <Expr>(), new List <IdentifierExpr>() { Expr.Ident(procRet) }); newCmds.Add(callCmd); } } node.TransferCmd = new ReturnCmd(Token.NoToken); } } else if (cmd is CallCmd) { // add assume(aliasing(funcPtr, calledProc)) var callCmd = cmd as CallCmd; var callee = callCmd.callee; // watch out: varg functions have trailing arg types in function name callee = callee.Split('.')[0]; var aaCmd = MkAssume(Expr.Ident("funcPtr", btype.Int), Expr.Ident(callee, btype.Int)); aaCmd.Attributes = new QKeyValue(Token.NoToken, "partition", new List <object>(), new QKeyValue(Token.NoToken, "slic", new List <object>(), aaCmd.Attributes)); newCmds.Add(aaCmd); //newCmds.Add(MkAssume(Expr.Ident("funcPtr", btype.Int), Expr.Ident(callee, btype.Int))); newCmds.Add(cmd); } else { newCmds.Add(cmd); } } node.Cmds = newCmds; return(node); }
public void Run() { Implementation impl; var rd = ""; while (true) { if (!impls.TryTake(out impl)) { break; } while (!resources.TryTake(out rd)) { Thread.Sleep(100); } sem.WaitOne(); var wd = Path.Combine(rd, impl.Name); // create new directory for each entrypoint Directory.CreateDirectory(wd); // create new directory for each entrypoint RemoteExec.CleanDirectory(wd); var pruneFile = Path.Combine(wd, "pruneSlice.bpl"); Program newprogram; // lock because Parsing a program is not thread-safe lock (fslock) { BoogieUtil.PrintProgram(program, pruneFile); // dump original program (so that each entrypoint has its own copy of program) newprogram = BoogieUtil.ReadAndOnlyResolve(pruneFile); // entrypoint's copy of the program } // slice the program by entrypoints Program shallowP = pruneDeepProcs(newprogram, ref edges, impl.Name, approximationDepth, implNames); BoogieUtil.pruneProcs(shallowP, shallowP.TopLevelDeclarations.OfType <Procedure>() .Where(proc => BoogieUtil.checkAttrExists("entrypoint", proc.Attributes)) .Select(proc => proc.Name) .FirstOrDefault()); File.Delete(pruneFile); lock (fslock) { BoogieUtil.PrintProgram(shallowP, pruneFile); // dump sliced program } sem.Release(); if (Driver.createEntryPointBplsOnly) { Console.WriteLine("Skipping AVN run for {0} given /createEntrypointBplsOnly", impl.Name); resources.Add(rd); continue; } if (!remotedirs.Contains(rd)) { Console.WriteLine("Running entrypoint {0} locally {{", impl.Name); if (deadlineReached) { return; } // spawn the job -- local var output = RemoteExec.run(wd, avnPath, string.Format("\"{0}\" {1}", pruneFile, avnArgs)); lock (fslock) { // delete temp files if (!keepFiles) { var files = System.IO.Directory.GetFiles(wd, "*.bpl"); foreach (var f in files) { System.IO.File.Delete(f); } } using (StreamWriter sw = new StreamWriter(Path.Combine(wd, "stdout.txt"))) output.Iter(s => sw.WriteLine("{0}", s)); } Console.WriteLine("Running entrypoint {0} locally }}", impl.Name); } else { // spawn the job -- remote if (psexecPath == null) { throw new FileNotFoundException("Cannot find PSEXEC!"); } // find the name of the machine from the remote folder name var machine = ""; var remoteroot = RemoteExec.GetRemoteFolder(rd, out machine); Console.WriteLine("Running entrypoint {0} on {1} {{", impl.Name, machine); // psexec machine -w remoteroot\impl remoteroot\fastavn\fastavn.exe remoteroot args wd = Path.Combine(remoteroot, impl.Name); var cmd = string.Format("{0} -w {1} {2} {3} {4}", machine, wd, Path.Combine(remoteroot, "fastavn", "AngelicVerifierNull.exe"), "pruneSlice.bpl", avnArgs); //Console.WriteLine("PSEXEC Running: {0}", cmd); if (deadlineReached) { return; } var output = RemoteExec.run(Directory.GetCurrentDirectory(), psexecPath, cmd); lock (fslock) { // delete temp files var td = Path.Combine(rd, impl.Name); if (debug) { Console.WriteLine("Getting files in directory: {0}", td); } var files = System.IO.Directory.GetFiles(td, "*.bpl"); foreach (var f in files) { if (debug) { Console.WriteLine("Deleting {0}", f); } System.IO.File.Delete(f); } // copy the results back var ld = Path.Combine(Directory.GetCurrentDirectory(), impl.Name); Directory.CreateDirectory(ld); RemoteExec.CleanDirectory(ld); RemoteExec.CopyFolder(rd, Directory.GetCurrentDirectory(), impl.Name, true); using (StreamWriter sw = new StreamWriter(Path.Combine(ld, "stdout.txt"))) output.Iter(s => sw.WriteLine("{0}", s)); } Console.WriteLine("Running entrypoint {0} on {1} }}", impl.Name, machine); } lock (fslock) { // collect and merge bugs var bugs = collectBugs(Path.Combine(Directory.GetCurrentDirectory(), impl.Name, bugReportFileName)); bugs.Iter(b => { if (!mergedBugs.ContainsKey(b)) { mergedBugs[b] = 0; } mergedBugs[b] += 1; }); Utils.Print(string.Format("Bugs found so far: {0}", mergedBugs.Count)); resources.Add(rd); } } }
// deletes calls to all entrypoints except mainproc, returns CorralMain since that this is the entrypoint // clears out all commands from the blocks with deleted calls private static string sliceMainForProc(Program program, string mainproc, HashSet <string> otherEPs) { Procedure entrypoint_proc = program.TopLevelDeclarations.OfType <Procedure>().Where(proc => BoogieUtil.checkAttrExists("entrypoint", proc.Attributes)).FirstOrDefault(); Debug.Assert(entrypoint_proc != null); Implementation entrypoint_impl = program.TopLevelDeclarations.OfType <Implementation>().Where(impl => impl.Name.Equals(entrypoint_proc.Name)).FirstOrDefault(); foreach (Block b in entrypoint_impl.Blocks) { if (b.Cmds.OfType <CallCmd>().Any(cc => cc.callee != mainproc && otherEPs.Contains(cc.callee))) { b.Cmds.Clear(); } } UnusedVarEliminator.Eliminate(program); return(entrypoint_proc.Name); }
public override Expr VisitNAryExpr(NAryExpr node) { //start with some negative cases if (!Matches || _toConsume.Count == 0) { Matches = false; return(base.VisitNAryExpr(node)); } //idea: if in anyExprMode, toConsume does not change --> we eat up any NaryExpr // if any of the arguments matches, the whole thing matches // nothing fancier now, because we only need IdentifierExpr and LiteralExpr if (_anyExprMode) { var anyMatches = false; var dispatched = new List <Expr>(); foreach (var a in node.Args) { Matches = true; dispatched.Add(VisitExpr(a)); anyMatches |= Matches; } Matches = anyMatches; return(new NAryExpr(node.tok, node.Fun, dispatched)); } // check if we need to switch to anyExprMode if (_toConsume.Peek() is NAryExpr && (((NAryExpr)_toConsume.Peek()).Fun) is FunctionCall && ((FunctionCall)((NAryExpr)_toConsume.Peek()).Fun).Func != null && BoogieUtil.checkAttrExists(BoogieKeyWords.AnyExpr, ((FunctionCall)((NAryExpr)_toConsume.Peek()).Fun).Func.Attributes)) { _anyExprMode = true; _toConsume.Pop(); ((NAryExpr)_toConsume.Peek()).Args.Reverse().Iter(arg => _toConsume.Push(arg)); var result = VisitNAryExpr(node); _anyExprMode = false; return(result); } if (!(_toConsume.Peek() is NAryExpr)) { //may still be an IdentifierExp intended to match any exp if (_toConsume.First() is IdentifierExpr && ((IdentifierExpr)_toConsume.Peek()).Decl != null && !BoogieUtil.checkAttrExists(BoogieKeyWords.IdExpr, ((IdentifierExpr)_toConsume.Peek()).Decl.Attributes)) { Substitution.Add(((IdentifierExpr)_toConsume.Peek()).Decl, node); _toConsume.Pop(); return(node); } Matches = false; return(base.VisitNAryExpr(node)); } var naeToConsume = (NAryExpr)_toConsume.Peek(); if (((NAryExpr)_toConsume.Peek()).Args.Count != node.Args.Count) { Matches = false; return(base.VisitNAryExpr(node)); } // now the positive cases // the same function is used if (naeToConsume.Fun.FunctionName == node.Fun.FunctionName) { _toConsume.Pop(); naeToConsume.Args.Reverse().Iter(arg => _toConsume.Push(arg)); return(base.VisitNAryExpr(node)); } // the function in toConsume has a declaration in TemplateVariables if (naeToConsume.Fun is FunctionCall && ((FunctionCall)naeToConsume.Fun).Func != null && naeToConsume.Fun.ArgumentCount == node.Fun.ArgumentCount && ((FunctionCall)naeToConsume.Fun).Func.InParams.Count == ((FunctionCall)node.Fun).Func.InParams.Count && ((FunctionCall)naeToConsume.Fun).Func.OutParams.Count == ((FunctionCall)node.Fun).Func.OutParams.Count && node.Fun is FunctionCall && AreAttributesASubset( ((FunctionCall)naeToConsume.Fun).Func.Attributes, ((FunctionCall)node.Fun).Func.Attributes)) { // do the argument types match? var tcFunc = ((FunctionCall)naeToConsume.Fun).Func; var nodeFunc = ((FunctionCall)node.Fun).Func; for (var i = 0; i < tcFunc.InParams.Count; i++) { if (!Equals(tcFunc.InParams[i].TypedIdent.Type, nodeFunc.InParams[i].TypedIdent.Type)) { Matches = false; return(base.VisitNAryExpr(node)); } } for (var i = 0; i < tcFunc.OutParams.Count; i++) { if (!Equals(tcFunc.OutParams[i].TypedIdent.Type, nodeFunc.OutParams[i].TypedIdent.Type)) { Matches = false; return(base.VisitNAryExpr(node)); } } FunctionSubstitution.Add(naeToConsume.Fun.FunctionName, node.Fun); _toConsume.Pop(); naeToConsume.Args.Reverse().Iter(arg => _toConsume.Push(arg)); return(base.VisitNAryExpr(node)); } Matches = false; return(base.VisitNAryExpr(node)); }
/// <summary> /// TODO: Refine this to only return variables of type pointers /// </summary> /// <param name="x"></param> /// <returns></returns> private bool IsPointerVariable(Variable x) { return(unknownGenProcs.ContainsKey(x.TypedIdent.Type.ToString()) && !BoogieUtil.checkAttrExists("scalar", x.Attributes)); //we will err on the side of treating variables as references }
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); }
//Change the body of any stub that returns a pointer into calling unknown() //TODO: only do this for procedures with a single return with a pointer type private void MkStubImplementation(List <Implementation> stubImpls, Procedure p) { List <Cmd> cmds = new List <Cmd>(); List <Variable> localVars = new List <Variable>(); stubs.Add(p.Name); foreach (var op in p.OutParams) { if (IsPointerVariable(op)) { cmds.Add(AllocatePointerAsUnknown(op)); } else { // Avoid using Havoc -- we'll let this fall on the floor as an // uninitialized variable. AVN will take care of concretizing it //cmds.Add(BoogieAstFactory.MkHavocVar(op)); } } foreach (var v in p.Modifies.Select(ie => ie.Decl)) { if (IsPointerVariable(v)) { cmds.Add(AllocatePointerAsUnknown(v)); } else { // unsupported Console.WriteLine("Warning: demonic havoc of global {0} in {1}", v.Name, p.Name); } } foreach (var ip in p.InParams) { if (!BoogieUtil.checkAttrExists("ref", ip.Attributes)) { continue; } string mapName = QKeyValue.FindStringAttribute(ip.Attributes, "ref"); if (mapName == null) { Utils.Print(String.Format("Expecting a map <name> with {:ref <name>} annotation on procedure {0}", p.Name), Utils.PRINT_TAG.AV_WARNING); continue; } var mapVars = prog.TopLevelDeclarations.OfType <Variable>().Where(x => x.Name == mapName && x.TypedIdent.Type.IsMap); if (mapVars.Count() != 1) { Utils.Print(String.Format("Mapname {0} provided in {{:ref}} for parameter {1} for procedure {2} has {3} matches, expecting exactly 1 match", mapName, ip.Name, p.Name, mapVars.Count()), Utils.PRINT_TAG.AV_WARNING); continue; } var tmpVar = BoogieAstFactory.MkLocal("__tmp_" + ip.Name, ip.TypedIdent.Type); localVars.Add(tmpVar); cmds.Add(AllocatePointerAsUnknown(tmpVar)); cmds.Add(BoogieAstFactory.MkMapAssign(mapVars.First(), IdentifierExpr.Ident(ip), IdentifierExpr.Ident(tmpVar))); } if (cmds.Count == 0) { return; //don't create a body if no statements } var blk = BoogieAstFactory.MkBlock(cmds, new ReturnCmd(Token.NoToken)); var blks = new List <Block>() { blk }; //don't insert the proc as it already exists var impl = BoogieAstFactory.MkImpl(p.Name, DropAnnotations(p.InParams), DropAnnotations(p.OutParams), new List <Variable>(), blks); ((Implementation)impl[1]).LocVars.AddRange(localVars); stubImpls.Add((Implementation)impl[1]); }
public static bool MatchSig(Implementation toMatch, DeclWithFormals dwf, Program boogieProgram, out QKeyValue toMatchAnyParamsAttributes, out int anyParamsPosition, out QKeyValue toMatchAnyParamsAttributesOut, out int anyParamsPositionOut, out Dictionary <Declaration, Expr> paramSubstitution, bool matchPtrs) { toMatchAnyParamsAttributes = null; anyParamsPosition = int.MaxValue; toMatchAnyParamsAttributesOut = null; anyParamsPositionOut = int.MaxValue; paramSubstitution = new Dictionary <Declaration, Expr>(); if (!ExprMatchVisitor.AreAttributesASubset(toMatch.Attributes, dwf.Attributes)) { return(false); } // match procedure name // Positive filters: AnyProcedure, NameMatches, ByName if (BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.AnyProcedure, toMatch.Attributes)) { //do nothing } else if (BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.NameMatches, toMatch.Attributes)) { var nmAttrParams = BoogieUtil.getAttr(ExprMatchVisitor.BoogieKeyWords.NameMatches, toMatch.Attributes); Debug.Assert(nmAttrParams.Count() == 1, "Expecting exactly one #NameMatches attribute, found " + nmAttrParams.Count()); var regex = nmAttrParams.First().ToString(); var m = Regex.Match(dwf.Name, regex); if (m.Success) { //do nothing } else { return(false); } } else if (toMatch.Name != dwf.Name) { return(false); } //Negative filter: NameNotMatches (can be multiple of them) if (BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.NameNotMatches, toMatch.Attributes)) { //get the params from multiple matching key var getAttrRepeated = new Func <QKeyValue, string, IList <IList <object> > >((attr, name) => { var ret = new List <IList <object> >(); for (; attr != null; attr = attr.Next) { if (attr.Key == name) { ret.Add(attr.Params); } } return(ret); }); var nmAttrParams = getAttrRepeated(toMatch.Attributes, ExprMatchVisitor.BoogieKeyWords.NameNotMatches); foreach (var nm in nmAttrParams) { if (Regex.Match(dwf.Name, nm.First().ToString()).Success) { return(false); } } } // if the procedure name is matched, it may still be that we are looking only for stubs if (BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.NoImplementation, toMatch.Attributes)) { foreach (var i in boogieProgram.Implementations) { if (i.Name == dwf.Name) { return(false); } } } Procedure dwfProc = null; if (dwf is Implementation) { dwfProc = ((Implementation)dwf).Proc; } else if (dwf is Procedure) { dwfProc = (Procedure)dwf; } if (!MatchParams(ref toMatchAnyParamsAttributes, ref anyParamsPosition, paramSubstitution, toMatch.InParams, toMatch.Proc.InParams, dwf.InParams, dwfProc.InParams, matchPtrs)) { return(false); } if (!MatchParams(ref toMatchAnyParamsAttributesOut, ref anyParamsPositionOut, paramSubstitution, toMatch.OutParams, toMatch.Proc.OutParams, dwf.OutParams, dwfProc.OutParams, matchPtrs)) { return(false); } return(true); }
private bool MatchCallCmd(CallCmd cmd, CmdRule rule, CallCmd toMatch, out List <Tuple <Dictionary <Declaration, Expr>, Dictionary <string, IAppliable> > > substitutions) { // question: why do we have a list of substitutions, here? // answer: the reason (right now) is AnyArgs: many arguments may match, the current semantics // is that we want to make the insertion for every match (example: memory accesses) substitutions = new List <Tuple <Dictionary <Declaration, Expr>, Dictionary <string, IAppliable> > >(); #region match procedure name //if (toMatch.callee == BoogieKeyWords.AnyProcedure) var matchCallee = rule.Prog.Procedures.FirstOrDefault(p => p.Name == toMatch.callee); if (matchCallee != null) { // procedure is declared in TemplateVariables if (matchCallee.HasAttribute(ExprMatchVisitor.BoogieKeyWords.NoImplementation)) { var hasImpl = false; _prog.Implementations .Iter(i => { if (i.Name == cmd.Proc.Name) { hasImpl = true; } }); //no match if (hasImpl) { return(false); } } } else if (toMatch.callee == cmd.Proc.Name) { // procedure matches by name } else { //no match return(false); } #endregion #region match out parameters //if (toMatch.Outs.Count == 1 // && toMatch.Outs[0].Name == BoogieKeyWords.AnyLhss) //{ // //matches anything --> do nothing/go on //} //else if (toMatch.Outs.Count == cmd.Outs.Count) { //TODO.. --> match, make substitution.. } else { //TODO.. --> match, make substitution.. } #endregion #region match arguments if (matchCallee != null && BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.AnyArgs, matchCallee.Attributes)) { //var anyArgsExpr = (NAryExpr) toMatch.Ins[0]; var anyArgsExpr = toMatch.Ins[0]; var atLeastOneMatch = false; foreach (var argCombo in cmd.Ins.Zip(cmd.Proc.InParams, Tuple.Create)) { var cmdArg = argCombo.Item1; var procArg = argCombo.Item2; // also match param type and attribute if (procArg.TypedIdent.Type.Equals(matchCallee.InParams[0].TypedIdent.Type) && ExprMatchVisitor.AreAttributesASubset(matchCallee.InParams[0].Attributes, procArg.Attributes)) { var emv = new ExprMatchVisitor(anyArgsExpr); emv.VisitExpr(cmdArg); if (emv.Matches) { atLeastOneMatch = true; substitutions.Add( new Tuple <Dictionary <Declaration, Expr>, Dictionary <string, IAppliable> >( emv.Substitution, emv.FunctionSubstitution)); } } } if (!atLeastOneMatch) { return(false); } } else { if (toMatch.Ins.Count != cmd.Ins.Count) { return(false); } for (var i = 0; i < cmd.Ins.Count; i++) { var arg = cmd.Ins[i]; var emv = new ExprMatchVisitor(toMatch.Ins[i]); emv.VisitExpr(arg); if (emv.Matches) { if (substitutions.Count == 0) { substitutions.Add(new Tuple <Dictionary <Declaration, Expr>, Dictionary <string, IAppliable> >(new Dictionary <Declaration, Expr>(), new Dictionary <string, IAppliable>())); } foreach (var kvp in emv.Substitution) { substitutions.First().Item1.Add(kvp.Key, kvp.Value); } foreach (var kvp in emv.FunctionSubstitution) { substitutions.First().Item2.Add(kvp.Key, kvp.Value); } } else { return(false); } } } #endregion return(true); }
public static bool MatchSig(Implementation toMatch, DeclWithFormals dwf, Program boogieProgram, out QKeyValue toMatchAnyParamsAttributes, out int anyParamsPosition, out QKeyValue toMatchAnyParamsAttributesOut, out int anyParamsPositionOut, out Dictionary <Declaration, Expr> paramSubstitution) { toMatchAnyParamsAttributes = null; anyParamsPosition = int.MaxValue; toMatchAnyParamsAttributesOut = null; anyParamsPositionOut = int.MaxValue; paramSubstitution = new Dictionary <Declaration, Expr>(); if (!ExprMatchVisitor.AreAttributesASubset(toMatch.Attributes, dwf.Attributes)) { return(false); } // match procedure name if (BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.AnyProcedure, toMatch.Attributes)) { //do nothing } else if (BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.NameMatches, toMatch.Attributes)) { var nmAttrParams = BoogieUtil.getAttr(ExprMatchVisitor.BoogieKeyWords.NameMatches, toMatch.Attributes); var regex = nmAttrParams.First().ToString(); var m = Regex.Match(dwf.Name, regex); if (m.Success) { //do nothing } else { return(false); } } else if (toMatch.Name != dwf.Name) { return(false); } // if the procedure name is matched, it may still be that we are looking only for stubs if (BoogieUtil.checkAttrExists(ExprMatchVisitor.BoogieKeyWords.NoImplementation, toMatch.Attributes)) { foreach (var i in boogieProgram.Implementations) { if (i.Name == dwf.Name) { return(false); } } } if (!MatchParams(ref toMatchAnyParamsAttributes, ref anyParamsPosition, paramSubstitution, toMatch.InParams, toMatch.Proc.InParams, dwf.InParams)) { return(false); } if (!MatchParams(ref toMatchAnyParamsAttributesOut, ref anyParamsPositionOut, paramSubstitution, toMatch.OutParams, toMatch.Proc.OutParams, dwf.OutParams)) { return(false); } return(true); }
static Program GetProgram(string filename) { var init = GetInputProgram(filename); if (Options.addInitialization) { ComputeandInitializeUninitializedLocals(init); } // Do some instrumentation for the input program if (Options.markAssumesAsSlic) { // Mark all assumes as "slic" var AddAnnotation = new Action <AssumeCmd>(ac => { ac.Attributes = new QKeyValue(Token.NoToken, "slic", new List <object>(), ac.Attributes); }); init.TopLevelDeclarations.OfType <Implementation>() .Iter(impl => impl.Blocks .Iter(blk => blk.Cmds.OfType <AssumeCmd>() .Iter(AddAnnotation))); } // Inline procedures supplied with {:inline} annotation cba.Driver.InlineProcedures(init); // Remove {:inline} impls init.RemoveTopLevelDeclarations(decl => (decl is Implementation) && (BoogieUtil.checkAttrExists("inline", decl.Attributes) || BoogieUtil.checkAttrExists("inline", (decl as Implementation).Proc.Attributes))); // Add {:entrypoint} to procs with {:harness} if (Options.useHarnessTag) { foreach (var decl in init.TopLevelDeclarations.OfType <NamedDeclaration>() .Where(d => QKeyValue.FindBoolAttribute(d.Attributes, "harness"))) { decl.AddAttribute("entrypoint"); } } // inlining introduces havoc statements; lets just delete them (TODO: make inlining not introduce redundant havoc statements) foreach (var impl in init.TopLevelDeclarations.OfType <Implementation>()) { impl.Blocks.Iter(blk => blk.Cmds.RemoveAll(cmd => cmd is HavocCmd)); } //Instrument to create the harness harnessInstrumentation = new Instrumentations.HarnessInstrumentation(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.useProvidedEntryPoints); harnessInstrumentation.DoInstrument(); //resolve+typecheck wo bothering about modSets CommandLineOptions.Clo.DoModSetAnalysis = true; init = BoogieUtil.ReResolve(init); CommandLineOptions.Clo.DoModSetAnalysis = false; // Update mod sets BoogieUtil.DoModSetAnalysis(init); if (Options.AddMapSelectNonNullAssumptions) { (new Instrumentations.AssertMapSelectsNonNull()).Visit(init); } BoogieUtil.pruneProcs(init, AvnAnnotations.CORRAL_MAIN_PROC); if (Options.deadCodeDetect) { // Tag branches as reachable var tup = InstrumentBranches.Run(init, AvnAnnotations.CORRAL_MAIN_PROC, Options.UseAliasAnalysisForAngelicAssertions, false); init = tup.Item1; // TODO: inject this information into the program itself DeadCodeBranchesDependencyInfo = tup.Item2; } return(init); }