zcov: / lib/Checker/ReturnStackAddressChecker.cpp


Files: 1 Branches Taken: 70.6% 24 / 34
Generated: 2010-02-10 01:31 Branches Executed: 94.1% 32 / 34
Line Coverage: 92.5% 49 / 53


Programs: 1 Runs 2897


       1                 : //== ReturnStackAddressChecker.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 ReturnStackAddressChecker, which is a path-sensitive
      11                 : // check which looks for the addresses of stack variables being returned to
      12                 : // callers.
      13                 : //
      14                 : //===----------------------------------------------------------------------===//
      15                 : 
      16                 : #include "GRExprEngineInternalChecks.h"
      17                 : #include "clang/Checker/PathSensitive/GRExprEngine.h"
      18                 : #include "clang/Checker/BugReporter/BugReporter.h"
      19                 : #include "clang/Checker/PathSensitive/CheckerVisitor.h"
      20                 : #include "clang/Basic/SourceManager.h"
      21                 : #include "llvm/ADT/SmallString.h"
      22                 : 
      23                 : using namespace clang;
      24                 : 
      25                 : namespace {
      26                 : class ReturnStackAddressChecker : 
                     2138: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
      27             2138:     public CheckerVisitor<ReturnStackAddressChecker> {      
      28                 :   BuiltinBug *BT;
      29                 : public:
      30             2138:   ReturnStackAddressChecker() : BT(0) {}
      31                 :   static void *getTag();
      32                 :   void PreVisitReturnStmt(CheckerContext &C, const ReturnStmt *RS);
      33                 : private:
      34                 :   void EmitStackError(CheckerContext &C, const MemRegion *R, const Expr *RetE);
      35                 : };
      36                 : }
      37                 : 
      38             2138: void clang::RegisterReturnStackAddressChecker(GRExprEngine &Eng) {
      39             2138:   Eng.registerCheck(new ReturnStackAddressChecker());
      40             2138: }
      41                 : 
      42             2138: void *ReturnStackAddressChecker::getTag() {
      43             2138:   static int x = 0; return &x;
      44                 : }
      45                 : 
      46                 : void ReturnStackAddressChecker::EmitStackError(CheckerContext &C,
      47                 :                                                const MemRegion *R,
      48               18:                                                const Expr *RetE) {
      49               18: 	ExplodedNode *N = C.GenerateSink();
      50                 : 
                        0: branch 0 not taken
                       18: branch 1 taken
      51               18: 	if (!N)
      52                0: 		return;
      53                 : 
                       14: branch 0 taken
                        4: branch 1 taken
      54               18: 	if (!BT)
      55               14: 		BT = new BuiltinBug("Return of address to stack-allocated memory");
      56                 : 
      57                 : 	// Generate a report for this bug.
      58               18: 	llvm::SmallString<512> buf;
      59               18: 	llvm::raw_svector_ostream os(buf);
      60               18: 	SourceRange range;
      61                 : 
      62                 : 	// Get the base region, stripping away fields and elements.
      63               18: 	R = R->getBaseRegion();
      64                 : 
      65                 : 	// Check if the region is a compound literal.
                        6: branch 1 taken
                       12: branch 2 taken
      66               18: 	if (const CompoundLiteralRegion* CR = dyn_cast<CompoundLiteralRegion>(R)) {    
      67                6: 		const CompoundLiteralExpr* CL = CR->getLiteralExpr();
      68                 : 		os << "Address of stack memory associated with a compound literal "
      69                 :           "declared on line "
      70                 :        << C.getSourceManager().getInstantiationLineNumber(CL->getLocStart())
      71                6:        << " returned to caller";    
      72                6: 		range = CL->getSourceRange();
      73                 : 	}
                        2: branch 1 taken
                       10: branch 2 taken
      74               12: 	else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(R)) {
      75                2: 		const Expr* ARE = AR->getExpr();
      76                2: 		SourceLocation L = ARE->getLocStart();
      77                2: 		range = ARE->getSourceRange();    
      78                 : 		os << "Address of stack memory allocated by call to alloca() on line "
      79                 :        << C.getSourceManager().getInstantiationLineNumber(L)
      80                2:        << " returned to caller";
      81                 : 	}
                        2: branch 1 taken
                        8: branch 2 taken
      82               10: 	else if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
      83                2: 		const BlockDecl *BD = BR->getCodeRegion()->getDecl();
      84                2: 		SourceLocation L = BD->getLocStart();
      85                2: 		range = BD->getSourceRange();
      86                 : 		os << "Address of stack-allocated block declared on line "
      87                 :        << C.getSourceManager().getInstantiationLineNumber(L)
      88                2:        << " returned to caller";
      89                 : 	}
                        8: branch 1 taken
                        0: branch 2 not taken
      90                8: 	else if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
      91                 : 		os << "Address of stack memory associated with local variable '"
      92                8:        << VR->getString() << "' returned";
      93                8: 		range = VR->getDecl()->getSourceRange();
      94                 : 	}
      95                 : 	else {
      96                0: 		assert(false && "Invalid region in ReturnStackAddressChecker.");
      97                0: 		return;
      98                 : 	}
      99                 : 
     100               18: 	RangedBugReport *report = new RangedBugReport(*BT, os.str(), N);
     101               18: 	report->addRange(RetE->getSourceRange());
                       18: branch 1 taken
                        0: branch 2 not taken
     102               18: 	if (range.isValid())
     103               18: 		report->addRange(range);
     104                 : 
                       18: branch 2 taken
                        0: branch 3 not taken
                       18: branch 5 taken
                        0: branch 6 not taken
     105               18: 	C.EmitReport(report);
     106                 : }	
     107                 : 
     108                 : void ReturnStackAddressChecker::PreVisitReturnStmt(CheckerContext &C,
     109             1333:                                                    const ReturnStmt *RS) {
     110                 :   
     111             1333:   const Expr *RetE = RS->getRetValue();
                      236: branch 0 taken
                     1097: branch 1 taken
     112             1333:   if (!RetE)
     113              236:     return;
     114                 :  
     115             1097:   SVal V = C.getState()->getSVal(RetE);
     116             1097:   const MemRegion *R = V.getAsRegion();
     117                 : 
                      294: branch 0 taken
                      803: branch 1 taken
                      276: branch 3 taken
                       18: branch 4 taken
                     1079: branch 5 taken
                       18: branch 6 taken
     118             1097:   if (!R || !R->hasStackStorage())
     119             1097:     return;  
     120                 :   
                       18: branch 1 taken
                        0: branch 2 not taken
     121               18:   if (R->hasStackStorage()) {
     122               18:     EmitStackError(C, R, RetE);
     123                 :     return;
                        0: branch 1 not taken
                     1097: branch 2 taken
     124             1097:   }
     125                0: }

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