zcov: / lib/Checker/UndefBranchChecker.cpp


Files: 1 Branches Taken: 53.8% 14 / 26
Generated: 2010-02-10 01:31 Branches Executed: 92.3% 24 / 26
Line Coverage: 97.8% 45 / 46


Programs: 1 Runs 2897


       1                 : //=== UndefBranchChecker.cpp -----------------------------------*- C++ -*--===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // This file defines UndefBranchChecker, which checks for undefined branch
      11                 : // condition.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "GRExprEngineInternalChecks.h"
      16                 : #include "clang/Checker/PathSensitive/Checker.h"
      17                 : 
      18                 : using namespace clang;
      19                 : 
      20                 : namespace {
      21                 : 
                     2138: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      22             2138: class UndefBranchChecker : public Checker {
      23                 :   BuiltinBug *BT;
      24                 : 
      25                 :   struct FindUndefExpr {
      26                 :     GRStateManager& VM;
      27                 :     const GRState* St;
      28                 : 
      29               30:     FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
      30                 : 
      31               40:     Expr* FindExpr(Expr* Ex) {
                        0: branch 1 not taken
                       40: branch 2 taken
      32               40:       if (!MatchesCriteria(Ex))
      33                0:         return 0;
      34                 : 
                       10: branch 4 taken
                       30: branch 5 taken
      35               40:       for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
                       10: branch 2 taken
                        0: branch 3 not taken
      36               10:         if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
      37               10:           Expr* E2 = FindExpr(ExI);
                       10: branch 0 taken
                        0: branch 1 not taken
      38               10:           if (E2) return E2;
      39                 :         }
      40                 : 
      41               30:       return Ex;
      42                 :     }
      43                 : 
      44               40:     bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
      45                 :   };
      46                 : 
      47                 : public:
      48             2138:   UndefBranchChecker() : BT(0) {}
      49                 :   static void *getTag();
      50                 :   void VisitBranchCondition(GRBranchNodeBuilder &Builder, GRExprEngine &Eng,
      51                 :                             Stmt *Condition, void *tag);
      52                 : };
      53                 : 
      54                 : }
      55                 : 
      56             2138: void clang::RegisterUndefBranchChecker(GRExprEngine &Eng) {
      57             2138:   Eng.registerCheck(new UndefBranchChecker());
      58             2138: }
      59                 : 
      60             2138: void *UndefBranchChecker::getTag() {
      61                 :   static int x;
      62             2138:   return &x;
      63                 : }
      64                 : 
      65                 : void UndefBranchChecker::VisitBranchCondition(GRBranchNodeBuilder &Builder, 
      66                 :                                               GRExprEngine &Eng,
      67             2248:                                               Stmt *Condition, void *tag) {
      68             2248:   const GRState *state = Builder.getState();
      69             2248:   SVal X = state->getSVal(Condition);
                       30: branch 1 taken
                     2218: branch 2 taken
      70             2248:   if (X.isUndef()) {
      71               30:     ExplodedNode *N = Builder.generateNode(state, true);
                       30: branch 0 taken
                        0: branch 1 not taken
      72               30:     if (N) {
      73               30:       N->markAsSink();
                       30: branch 0 taken
                        0: branch 1 not taken
      74               30:       if (!BT)
      75               30:         BT = new BuiltinBug("Branch condition evaluates to a garbage value");
      76                 : 
      77                 :       // What's going on here: we want to highlight the subexpression of the
      78                 :       // condition that is the most likely source of the "uninitialized
      79                 :       // branch condition."  We do a recursive walk of the condition's
      80                 :       // subexpressions and roughly look for the most nested subexpression
      81                 :       // that binds to Undefined.  We then highlight that expression's range.
      82               30:       BlockEdge B = cast<BlockEdge>(N->getLocation());
      83               30:       Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
                        0: branch 0 not taken
                       30: branch 1 taken
      84               30:       assert (Ex && "Block must have a terminator.");
      85                 : 
      86                 :       // Get the predecessor node and check if is a PostStmt with the Stmt
      87                 :       // being the terminator condition.  We want to inspect the state
      88                 :       // of that node instead because it will contain main information about
      89                 :       // the subexpressions.
                        0: branch 1 not taken
                       30: branch 2 taken
      90               30:       assert (!N->pred_empty());
      91                 : 
      92                 :       // Note: any predecessor will do.  They should have identical state,
      93                 :       // since all the BlockEdge did was act as an error sink since the value
      94                 :       // had to already be undefined.
      95               30:       ExplodedNode *PrevN = *N->pred_begin();
      96               30:       ProgramPoint P = PrevN->getLocation();
      97               30:       const GRState* St = N->getState();
      98                 : 
                       30: branch 1 taken
                        0: branch 2 not taken
      99               30:       if (PostStmt* PS = dyn_cast<PostStmt>(&P))
                       30: branch 1 taken
                        0: branch 2 not taken
     100               30:         if (PS->getStmt() == Ex)
     101               30:           St = PrevN->getState();
     102                 : 
     103               30:       FindUndefExpr FindIt(Eng.getStateManager(), St);
     104               30:       Ex = FindIt.FindExpr(Ex);
     105                 : 
     106                 :       // Emit the bug report.
     107               30:       EnhancedBugReport *R = new EnhancedBugReport(*BT, BT->getDescription(),N);
     108               30:       R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, Ex);
     109               30:       R->addRange(Ex->getSourceRange());
     110                 : 
     111               30:       Eng.getBugReporter().EmitReport(R);
     112                 :     }
     113                 : 
     114               30:     Builder.markInfeasible(true);
     115               30:     Builder.markInfeasible(false);
     116             2248:   }
     117             2248: }

Generated: 2010-02-10 01:31 by zcov