 |
|
 |
|
| 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 |
| |
 |
|
 |
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