blob: 49e19434cb7ef4fb19b76331c2d329428a69cf2b [file] [log] [blame]
Zhongxing Xu259d4642009-11-04 01:43:07 +00001//=== VLASizeChecker.cpp - Undefined dereference checker --------*- 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 defines two VLASizeCheckers, a builtin check in GRExprEngine that
11// performs checks for declaration of VLA of undefined or zero size.
12//
13//===----------------------------------------------------------------------===//
14
Ted Kremenek795c6112009-11-06 21:51:50 +000015#include "GRExprEngineInternalChecks.h"
16#include "clang/Analysis/PathSensitive/Checker.h"
Zhongxing Xu259d4642009-11-04 01:43:07 +000017#include "clang/Analysis/PathSensitive/GRExprEngine.h"
18#include "clang/Analysis/PathSensitive/BugReporter.h"
19
20using namespace clang;
21
Ted Kremenek795c6112009-11-06 21:51:50 +000022namespace {
23class VISIBILITY_HIDDEN UndefSizedVLAChecker : public Checker {
24 BugType *BT;
25
26public:
27 UndefSizedVLAChecker() : BT(0) {}
28 static void *getTag();
29 ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
30 const GRState *state, Stmt *S, GRExprEngine &Eng);
31};
32
33class VISIBILITY_HIDDEN ZeroSizedVLAChecker : public Checker {
34 BugType *BT;
35
36public:
37 ZeroSizedVLAChecker() : BT(0) {}
38 static void *getTag();
39 ExplodedNode *CheckType(QualType T, ExplodedNode *Pred,
40 const GRState *state, Stmt *S, GRExprEngine &Eng);
41};
42} // end anonymous namespace
43
44void clang::RegisterVLASizeChecker(GRExprEngine &Eng) {
45 Eng.registerCheck(new UndefSizedVLAChecker());
46 Eng.registerCheck(new ZeroSizedVLAChecker());
47}
48
Zhongxing Xu259d4642009-11-04 01:43:07 +000049void *UndefSizedVLAChecker::getTag() {
50 static int x = 0;
51 return &x;
52}
53
54ExplodedNode *UndefSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
55 const GRState *state,
56 Stmt *S, GRExprEngine &Eng) {
57 GRStmtNodeBuilder &Builder = Eng.getBuilder();
58 BugReporter &BR = Eng.getBugReporter();
59
60 if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
61 // FIXME: Handle multi-dimensional VLAs.
62 Expr* SE = VLA->getSizeExpr();
63 SVal Size_untested = state->getSVal(SE);
64
65 if (Size_untested.isUndef()) {
66 if (ExplodedNode* N = Builder.generateNode(S, state, Pred)) {
67 N->markAsSink();
68 if (!BT)
Ted Kremenek2980b972009-11-06 00:44:32 +000069 BT = new BuiltinBug("Declared variable-length array (VLA) uses a "
70 "garbage value as its size");
Zhongxing Xu259d4642009-11-04 01:43:07 +000071
72 EnhancedBugReport *R =
73 new EnhancedBugReport(*BT, BT->getName().c_str(), N);
74 R->addRange(SE->getSourceRange());
75 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
76 BR.EmitReport(R);
77 }
78 return 0;
79 }
80 }
81 return Pred;
82}
83
84void *ZeroSizedVLAChecker::getTag() {
85 static int x;
86 return &x;
87}
88
89ExplodedNode *ZeroSizedVLAChecker::CheckType(QualType T, ExplodedNode *Pred,
90 const GRState *state, Stmt *S,
91 GRExprEngine &Eng) {
92 GRStmtNodeBuilder &Builder = Eng.getBuilder();
93 BugReporter &BR = Eng.getBugReporter();
94
95 if (VariableArrayType* VLA = dyn_cast<VariableArrayType>(T)) {
96 // FIXME: Handle multi-dimensional VLAs.
97 Expr* SE = VLA->getSizeExpr();
98 SVal Size_untested = state->getSVal(SE);
99
100 DefinedOrUnknownSVal *Size = dyn_cast<DefinedOrUnknownSVal>(&Size_untested);
101 // Undefined size is checked in another checker.
102 if (!Size)
103 return Pred;
104
105 const GRState *zeroState = state->Assume(*Size, false);
106 state = state->Assume(*Size, true);
107
108 if (zeroState && !state) {
109 if (ExplodedNode* N = Builder.generateNode(S, zeroState, Pred)) {
110 N->markAsSink();
111 if (!BT)
Ted Kremenekc92ff052009-11-05 08:30:12 +0000112 BT = new BugType("Declared variable-length array (VLA) has zero size",
Zhongxing Xu259d4642009-11-04 01:43:07 +0000113 "Logic error");
114
115 EnhancedBugReport *R =
116 new EnhancedBugReport(*BT, BT->getName().c_str(), N);
117 R->addRange(SE->getSourceRange());
118 R->addVisitorCreator(bugreporter::registerTrackNullOrUndefValue, SE);
119 BR.EmitReport(R);
120 }
121 }
122 if (!state)
123 return 0;
124
125 return Builder.generateNode(S, state, Pred);
126 }
127 else
128 return Pred;
129}
130