예제 #1
0
파일: Program.cs 프로젝트: zvonimir/corral
        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);
        }
예제 #2
0
            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);
            }
예제 #3
0
        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;
            }
        }
예제 #4
0
파일: Visitor.cs 프로젝트: zvonimir/corral
        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));
        }
예제 #5
0
 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);
 }
예제 #6
0
        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));
                }
예제 #8
0
        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);
        }
예제 #9
0
파일: Visitor.cs 프로젝트: zvonimir/corral
        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));
        }
예제 #10
0
파일: Visitor.cs 프로젝트: zvonimir/corral
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
            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);
            }
예제 #13
0
        // 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);
        }
예제 #14
0
        public override CBAProgram runCBAPass(CBAProgram p)
        {
            p.Typecheck();

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

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

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

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

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

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

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

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

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

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

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

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

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

            vp.run(program);

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

            var trace = mapBackTraceRecord(vp.trace);

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

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

            var rtprog = rt.getProgram();

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

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

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

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

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

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

            program = inlp.run(program);

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

            compress.VisitProgram(ret);


            return(new CBAProgram(ret, program.mainProcName, 0));
        }
예제 #15
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);
        }
예제 #16
0
        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);
        }
예제 #17
0
            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);
                    }
                }
            }
예제 #18
0
        // 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);
        }
예제 #19
0
파일: Visitor.cs 프로젝트: zvonimir/corral
        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));
        }
예제 #20
0
 /// <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
 }
예제 #21
0
            private void CreateMainProcedure(Function reach)
            {
                //blocks
                List <Block>    mainBlocks = new List <Block>();
                List <Variable> locals     = new List <Variable>();

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

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

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

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

                    entrypoints.Add(impl.Name);

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


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


                    locals.AddRange(rets);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                mainProcImpl[0].AddAttribute("entrypoint");
                prog.AddTopLevelDeclarations(mainProcImpl);
            }
예제 #22
0
            //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]);
            }
예제 #23
0
        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);
        }
예제 #24
0
파일: Program.cs 프로젝트: smackers/corral
        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);
        }
예제 #25
0
        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);
        }
예제 #26
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)));
            }

            // 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);
        }