zcov: / lib/Checker/VLASizeChecker.cpp


Files: 1 Branches Taken: 69.2% 18 / 26
Generated: 2010-02-10 01:31 Branches Executed: 92.3% 24 / 26
Line Coverage: 92.5% 37 / 40


Programs: 1 Runs 2897


       1                 : //=== VLASizeChecker.cpp - Undefined dereference checker --------*- 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 defines VLASizeChecker, a builtin check in GRExprEngine that 
      11                 : // performs checks for declaration of VLA of undefined or zero size.
      12                 : //
      13                 : //===----------------------------------------------------------------------===//
      14                 : 
      15                 : #include "GRExprEngineInternalChecks.h"
      16                 : #include "clang/Checker/PathSensitive/CheckerVisitor.h"
      17                 : #include "clang/Checker/PathSensitive/GRExprEngine.h"
      18                 : #include "clang/Checker/BugReporter/BugReporter.h"
      19                 : 
      20                 : using namespace clang;
      21                 : 
      22                 : namespace {
                     2138: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      23             2138: class VLASizeChecker : public CheckerVisitor<VLASizeChecker> {
      24                 :   BugType *BT_zero;
      25                 :   BugType *BT_undef;
      26                 :   
      27                 : public:
      28             2138:   VLASizeChecker() : BT_zero(0), BT_undef(0) {}
      29             2138:   static void *getTag() { static int tag = 0; return &tag; }
      30                 :   void PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS);
      31                 : };
      32                 : } // end anonymous namespace
      33                 : 
      34             2138: void clang::RegisterVLASizeChecker(GRExprEngine &Eng) {
      35             2138:   Eng.registerCheck(new VLASizeChecker());
      36             2138: }
      37                 : 
      38             2438: void VLASizeChecker::PreVisitDeclStmt(CheckerContext &C, const DeclStmt *DS) {
                        0: branch 1 not taken
                     2438: branch 2 taken
      39             2438:   if (!DS->isSingleDecl())
      40                0:     return;
      41                 :   
      42             2438:   const VarDecl *VD = dyn_cast<VarDecl>(DS->getSingleDecl());
                        0: branch 0 not taken
                     2438: branch 1 taken
      43             2438:   if (!VD)
      44                0:     return;
      45                 :   
      46                 :   const VariableArrayType *VLA
      47             2438:     = C.getASTContext().getAsVariableArrayType(VD->getType());
                     2392: branch 0 taken
                       46: branch 1 taken
      48             2438:   if (!VLA)
      49             2392:     return;
      50                 : 
      51                 :   // FIXME: Handle multi-dimensional VLAs.
      52               46:   const Expr* SE = VLA->getSizeExpr();
      53               46:   const GRState *state = C.getState();
      54               46:   SVal sizeV = state->getSVal(SE);
      55                 : 
                       10: branch 1 taken
                       36: branch 2 taken
      56               46:   if (sizeV.isUndef()) {
      57                 :     // Generate an error node.
      58               10:     ExplodedNode *N = C.GenerateSink();
                        0: branch 0 not taken
                       10: branch 1 taken
      59               10:     if (!N)
      60               20:       return;
      61                 :     
                       10: branch 0 taken
                        0: branch 1 not taken
      62               10:     if (!BT_undef)
      63                 :       BT_undef = new BuiltinBug("Declared variable-length array (VLA) uses a "
      64               10:                                 "garbage value as its size");
      65                 : 
      66                 :     EnhancedBugReport *report =
      67               10:       new EnhancedBugReport(*BT_undef, BT_undef->getName(), N);
      68               10:     report->addRange(SE->getSourceRange());
      69               10:     report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
      70               10:     C.EmitReport(report);
      71                 :     return;
      72                 :   }
      73                 :   
      74                 :   // Check if the size is zero.
      75               36:   DefinedOrUnknownSVal sizeD = cast<DefinedOrUnknownSVal>(sizeV);
      76                 : 
      77                 :   const GRState *stateNotZero, *stateZero;
      78               36:   llvm::tie(stateNotZero, stateZero) = state->Assume(sizeD);
      79                 : 
                       24: branch 0 taken
                       12: branch 1 taken
                       10: branch 2 taken
                       14: branch 3 taken
      80               36:   if (stateZero && !stateNotZero) {
      81               10:     ExplodedNode* N = C.GenerateSink(stateZero);
                       10: branch 0 taken
                        0: branch 1 not taken
      82               10:     if (!BT_zero)
      83                 :       BT_zero = new BuiltinBug("Declared variable-length array (VLA) has zero "
      84               10:                                "size");
      85                 : 
      86                 :     EnhancedBugReport *report =
      87               10:       new EnhancedBugReport(*BT_zero, BT_zero->getName(), N);
      88               10:     report->addRange(SE->getSourceRange());
      89               10:     report->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
      90               10:     C.EmitReport(report);
      91                 :     return;
      92                 :   }
      93                 :  
      94                 :   // From this point on, assume that the size is not zero.
                       26: branch 2 taken
                       10: branch 3 taken
                       26: branch 5 taken
                       20: branch 6 taken
      95               26:   C.addTransition(stateNotZero);
      96                0: }

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