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