zcov: / lib/Checker/ArrayBoundChecker.cpp


Files: 1 Branches Taken: 70.0% 14 / 20
Generated: 2010-02-10 01:31 Branches Executed: 90.0% 18 / 20
Line Coverage: 96.9% 31 / 32


Programs: 1 Runs 2897


       1                 : //== ArrayBoundChecker.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 ArrayBoundChecker, which is a path-sensitive check
      11                 : // which looks for an out-of-bound array element access.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "GRExprEngineInternalChecks.h"
      16                 : #include "clang/Checker/PathSensitive/GRExprEngine.h"
      17                 : #include "clang/Checker/BugReporter/BugReporter.h"
      18                 : #include "clang/Checker/PathSensitive/CheckerVisitor.h"
      19                 : 
      20                 : using namespace clang;
      21                 : 
      22                 : namespace {
      23                 : class ArrayBoundChecker : 
                     1845: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      24             1845:     public CheckerVisitor<ArrayBoundChecker> {      
      25                 :   BuiltinBug *BT;
      26                 : public:
      27             1845:     ArrayBoundChecker() : BT(0) {}
      28                 :     static void *getTag();
      29                 :     void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
      30                 : };
      31                 : }
      32                 : 
      33             1845: void clang::RegisterArrayBoundChecker(GRExprEngine &Eng) {
      34             1845:   Eng.registerCheck(new ArrayBoundChecker());
      35             1845: }
      36                 : 
      37             1845: void *ArrayBoundChecker::getTag() {
      38             1845:   static int x = 0; return &x;
      39                 : }
      40                 : 
      41             9033: void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
      42                 :   // Check for out of bound array element access.
      43             9033:   const MemRegion *R = l.getAsRegion();
                        2: branch 0 taken
                     9031: branch 1 taken
      44             9033:   if (!R)
      45                2:     return;
      46                 : 
      47             9031:   R = R->StripCasts();
      48                 : 
      49             9031:   const ElementRegion *ER = dyn_cast<ElementRegion>(R);
                     8765: branch 0 taken
                      266: branch 1 taken
      50             9031:   if (!ER)
      51             8765:     return;
      52                 : 
      53                 :   // Get the index of the accessed element.
      54              266:   DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
      55                 : 
      56              266:   const GRState *state = C.getState();
      57                 : 
      58                 :   // Get the size of the array.
      59                 :   DefinedOrUnknownSVal NumElements 
      60                 :     = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(), 
      61              266:                                          ER->getValueType(C.getASTContext()));
      62                 : 
      63              266:   const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
      64              266:   const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
                      205: branch 0 taken
                       61: branch 1 taken
                        5: branch 2 taken
                      200: branch 3 taken
      65              266:   if (StOutBound && !StInBound) {
      66                5:     ExplodedNode *N = C.GenerateSink(StOutBound);
                        0: branch 0 not taken
                        5: branch 1 taken
      67                5:     if (!N)
      68                5:       return;
      69                 :   
                        5: branch 0 taken
                        0: branch 1 not taken
      70                5:     if (!BT)
      71                 :       BT = new BuiltinBug("Out-of-bound array access",
      72                5:                        "Access out-of-bound array element (buffer overflow)");
      73                 : 
      74                 :     // FIXME: It would be nice to eventually make this diagnostic more clear,
      75                 :     // e.g., by referencing the original declaration or by saying *why* this
      76                 :     // reference is outside the range.
      77                 : 
      78                 :     // Generate a report for this bug.
      79                 :     RangedBugReport *report = 
      80                5:       new RangedBugReport(*BT, BT->getDescription(), N);
      81                 : 
      82                5:     report->addRange(S->getSourceRange());
      83                5:     C.EmitReport(report);
      84                 :     return;
      85                 :   }
      86                 :   
      87                 :   // Array bound check succeeded.  From this point forward the array bound
      88                 :   // should always succeed.
                        0: branch 0 not taken
                      261: branch 1 taken
      89              261:   assert(StInBound);
                      261: branch 2 taken
                        5: branch 3 taken
      90              261:   C.addTransition(StInBound);
      91                0: }

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