blob: 34a5631edd3e7e0c73e74028e8bd63b0504722dc [file] [log] [blame]
Zhongxing Xu58e689f2009-11-11 12:33:27 +00001//== 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/Analysis/PathSensitive/GRExprEngine.h"
17#include "clang/Analysis/PathSensitive/BugReporter.h"
18#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
19
20using namespace clang;
21
22namespace {
23class VISIBILITY_HIDDEN ArrayBoundChecker :
24 public CheckerVisitor<ArrayBoundChecker> {
25 BuiltinBug *BT;
26public:
27 ArrayBoundChecker() : BT(0) {}
28 static void *getTag();
29 void VisitLocation(CheckerContext &C, const Stmt *S, SVal l);
30};
31}
32
33void clang::RegisterArrayBoundChecker(GRExprEngine &Eng) {
34 Eng.registerCheck(new ArrayBoundChecker());
35}
36
37void *ArrayBoundChecker::getTag() {
38 static int x = 0; return &x;
39}
40
41void ArrayBoundChecker::VisitLocation(CheckerContext &C, const Stmt *S, SVal l){
42 // Check for out of bound array element access.
43 const MemRegion *R = l.getAsRegion();
44 if (!R)
45 return;
46
47 R = R->StripCasts();
48
49 const ElementRegion *ER = dyn_cast<ElementRegion>(R);
50 if (!ER)
51 return;
52
53 // Get the index of the accessed element.
54 DefinedOrUnknownSVal &Idx = cast<DefinedOrUnknownSVal>(ER->getIndex());
55
56 const GRState *state = C.getState();
57
58 // Get the size of the array.
Zhongxing Xue884ff82009-11-12 02:48:32 +000059 DefinedOrUnknownSVal NumElements
60 = C.getStoreManager().getSizeInElements(state, ER->getSuperRegion());
Zhongxing Xu58e689f2009-11-11 12:33:27 +000061
62 const GRState *StInBound = state->AssumeInBound(Idx, NumElements, true);
63 const GRState *StOutBound = state->AssumeInBound(Idx, NumElements, false);
64 if (StOutBound && !StInBound) {
65 ExplodedNode *N = C.GenerateNode(S, StOutBound, true);
66
67 if (!N)
68 return;
69
70 if (!BT)
71 BT = new BuiltinBug("Out-of-bound array access",
72 "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 new RangedBugReport(*BT, BT->getDescription().c_str(), N);
81
82 report->addRange(S->getSourceRange());
83
84 C.EmitReport(report);
85 }
86}