zcov: / lib/Checker/ReturnPointerRangeChecker.cpp


Files: 1 Branches Taken: 62.5% 15 / 24
Generated: 2010-02-10 01:31 Branches Executed: 91.7% 22 / 24
Line Coverage: 97.1% 33 / 34


Programs: 1 Runs 2897


       1                 : //== ReturnPointerRangeChecker.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 ReturnPointerRangeChecker, which is a path-sensitive check
      11                 : // which looks for an out-of-bound pointer being returned to callers.
      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 ReturnPointerRangeChecker : 
                     1845: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      24             1845:     public CheckerVisitor<ReturnPointerRangeChecker> {      
      25                 :   BuiltinBug *BT;
      26                 : public:
      27             1845:     ReturnPointerRangeChecker() : BT(0) {}
      28                 :     static void *getTag();
      29                 :     void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
      30                 : };
      31                 : }
      32                 : 
      33             1845: void clang::RegisterReturnPointerRangeChecker(GRExprEngine &Eng) {
      34             1845:   Eng.registerCheck(new ReturnPointerRangeChecker());
      35             1845: }
      36                 : 
      37             1845: void *ReturnPointerRangeChecker::getTag() {
      38             1845:   static int x = 0; return &x;
      39                 : }
      40                 : 
      41                 : void ReturnPointerRangeChecker::PreVisitReturnStmt(CheckerContext &C,
      42             1174:                                                    const ReturnStmt *RS) {
      43             1174:   const GRState *state = C.getState();
      44                 : 
      45             1174:   const Expr *RetE = RS->getRetValue();
                      226: branch 0 taken
                      948: branch 1 taken
      46             1174:   if (!RetE)
      47              226:     return;
      48                 :  
      49              948:   SVal V = state->getSVal(RetE);
      50              948:   const MemRegion *R = V.getAsRegion();
                      742: branch 0 taken
                      206: branch 1 taken
      51              948:   if (!R)
      52              946:     return;
      53                 : 
      54              206:   R = R->StripCasts();
                        0: branch 0 not taken
                      206: branch 1 taken
      55              206:   if (!R)
      56                 :     return;
      57                 : 
      58              206:   const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R);
                      204: branch 0 taken
                        2: branch 1 taken
      59              206:   if (!ER)
      60                 :     return;
      61                 : 
      62                2:   DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
      63                 : 
      64                 :   // FIXME: All of this out-of-bounds checking should eventually be refactored
      65                 :   // into a common place.
      66                 : 
      67                 :   DefinedOrUnknownSVal NumElements
      68                 :     = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion(),
      69                2:                                            ER->getValueType(C.getASTContext()));
      70                 : 
      71                2:   const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
      72                2:   const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
                        2: branch 0 taken
                        0: branch 1 not taken
                        2: branch 2 taken
                        0: branch 3 not taken
      73                2:   if (StOutBound && !StInBound) {
      74                2:     ExplodedNode *N = C.GenerateSink(StOutBound);
      75                 : 
                        0: branch 0 not taken
                        2: branch 1 taken
      76                2:     if (!N)
      77                 :       return;
      78                 :   
      79                 :     // FIXME: This bug correspond to CWE-466.  Eventually we should have bug
      80                 :     // types explicitly reference such exploit categories (when applicable).
                        2: branch 0 taken
                        0: branch 1 not taken
      81                2:     if (!BT)
      82                 :       BT = new BuiltinBug("Return of pointer value outside of expected range",
      83                 :            "Returned pointer value points outside the original object "
      84                2:            "(potential buffer overflow)");
      85                 : 
      86                 :     // FIXME: It would be nice to eventually make this diagnostic more clear,
      87                 :     // e.g., by referencing the original declaration or by saying *why* this
      88                 :     // reference is outside the range.
      89                 : 
      90                 :     // Generate a report for this bug.
      91                 :     RangedBugReport *report = 
      92                2:       new RangedBugReport(*BT, BT->getDescription(), N);
      93                 : 
      94                2:     report->addRange(RetE->getSourceRange());
      95                2:     C.EmitReport(report);
                        2: branch 1 taken
                        0: branch 2 not taken
                        2: branch 4 taken
                      946: branch 5 taken
      96                2:   }
      97                0: }

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