blob: c1128ccd1c41b4020b17fa7265f2238e49ca4f14 [file] [log] [blame]
Ted Kremenek78d46242008-07-22 16:21:24 +00001//=-- GRExprEngineInternalChecks.cpp - Builtin GRExprEngine Checks---*- 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 the BugType classes used by GRExprEngine to report
11// bugs derived from builtin checks in the path-sensitive engine.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/PathSensitive/BugReporter.h"
16#include "clang/Analysis/PathSensitive/GRExprEngine.h"
17#include "llvm/Support/Compiler.h"
18
19
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// Utility functions.
24//===----------------------------------------------------------------------===//
25
26template <typename ITERATOR> inline
27ExplodedNode<ValueState>* GetNode(ITERATOR I) {
28 return *I;
29}
30
31template <> inline
32ExplodedNode<ValueState>* GetNode(GRExprEngine::undef_arg_iterator I) {
33 return I->first;
34}
35
36//===----------------------------------------------------------------------===//
37// Bug Descriptions.
38//===----------------------------------------------------------------------===//
39
40namespace {
41class VISIBILITY_HIDDEN BuiltinBug : public BugTypeCacheLocation {
42 const char* name;
43 const char* desc;
44public:
45 BuiltinBug(const char* n, const char* d) : name(n), desc(d) {}
46 virtual const char* getName() const { return name; }
47 virtual const char* getDescription() const { return desc; }
48 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) = 0;
49 virtual void EmitWarnings(BugReporter& BR) {
50 EmitBuiltinWarnings(BR, cast<GRBugReporter>(BR).getEngine());
51 }
52
53 template <typename ITER>
54 void Emit(BugReporter& BR, ITER I, ITER E) {
55 for (; I != E; ++I) {
56 BugReport R(*this, GetNode(I));
57 BR.EmitWarning(R);
58 }
59 }
60};
61
62class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
63public:
64 NullDeref() : BuiltinBug("null dereference",
65 "Dereference of null pointer.") {}
66
67 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
68 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
69 }
70};
71
72class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
73public:
74 UndefinedDeref() : BuiltinBug("bad dereference",
75 "Dereference of undefined value.") {}
76
77 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
78 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
79 }
80};
81
82class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
83public:
84 DivZero() : BuiltinBug("divide-by-zero",
85 "Division by zero/undefined value.") {}
86
87 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
88 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
89 }
90};
91
92class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
93public:
94 UndefResult() : BuiltinBug("undefined result",
95 "Result of operation is undefined.") {}
96
97 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
98 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
99 }
100};
101
102class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
103public:
104 BadCall()
105 : BuiltinBug("invalid function call",
106 "Called function is a NULL or undefined function pointer value.") {}
107
108 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
109 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
110 }
111};
112
113class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
114public:
115 BadArg() : BuiltinBug("bad argument",
116 "Pass-by-value argument in function is undefined.") {}
117
118 BadArg(const char* d) : BuiltinBug("bad argument", d) {}
119
120 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
121 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
122 E = Eng.undef_arg_end(); I!=E; ++I) {
123
124 // Generate a report for this bug.
125 RangedBugReport report(*this, I->first);
126 report.addRange(I->second->getSourceRange());
127
128 // Emit the warning.
129 BR.EmitWarning(report);
130 }
131 }
132};
133
134class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
135public:
136 BadMsgExprArg()
137 : BadArg("Pass-by-value argument in message expression is undefined.") {}
138
139 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
140 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
141 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
142
143 // Generate a report for this bug.
144 RangedBugReport report(*this, I->first);
145 report.addRange(I->second->getSourceRange());
146
147 // Emit the warning.
148 BR.EmitWarning(report);
149 }
150 }
151};
152
153class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
154public:
155 BadReceiver()
156 : BuiltinBug("bad receiver",
157 "Receiver in message expression is an uninitialized value.") {}
158
159 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
160 for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
161 End = Eng.undef_receivers_end(); I!=End; ++I) {
162
163 // Generate a report for this bug.
164 RangedBugReport report(*this, *I);
165
166 ExplodedNode<ValueState>* N = *I;
167 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
168 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
169 assert (E && "Receiver cannot be NULL");
170 report.addRange(E->getSourceRange());
171
172 // Emit the warning.
173 BR.EmitWarning(report);
174 }
175 }
176};
177
178class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
179public:
180 RetStack() : BuiltinBug("return of stack address",
181 "Address of stack-allocated variable returned.") {}
182
183 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
184 Emit(BR, Eng.ret_stackaddr_begin(), Eng.ret_stackaddr_end());
185 }
186};
187
188
189class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
190 struct VISIBILITY_HIDDEN FindUndefExpr {
191 ValueStateManager& VM;
192 const ValueState* St;
193
194 FindUndefExpr(ValueStateManager& V, const ValueState* S) : VM(V), St(S) {}
195
196 Expr* FindExpr(Expr* Ex) {
197
198 if (!MatchesCriteria(Ex))
199 return 0;
200
201 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end(); I!=E; ++I)
202 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
203 Expr* E2 = FindExpr(ExI);
204 if (E2) return E2;
205 }
206
207 return Ex;
208 }
209
210 bool MatchesCriteria(Expr* Ex) { return VM.GetRVal(St, Ex).isUndef(); }
211 };
212
213public:
214 UndefBranch()
215 : BuiltinBug("uninitialized value",
216 "Branch condition evaluates to an uninitialized value.") {}
217
218 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
219 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
220 E=Eng.undef_branches_end(); I!=E; ++I) {
221
222 // What's going on here: we want to highlight the subexpression of the
223 // condition that is the most likely source of the "uninitialized
224 // branch condition." We do a recursive walk of the condition's
225 // subexpressions and roughly look for the most nested subexpression
226 // that binds to Undefined. We then highlight that expression's range.
227
228 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
229 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
230 assert (Ex && "Block must have a terminator.");
231
232 // Get the predecessor node and check if is a PostStmt with the Stmt
233 // being the terminator condition. We want to inspect the state
234 // of that node instead because it will contain main information about
235 // the subexpressions.
236
237 assert (!(*I)->pred_empty());
238
239 // Note: any predecessor will do. They should have identical state,
240 // since all the BlockEdge did was act as an error sink since the value
241 // had to already be undefined.
242 ExplodedNode<ValueState> *N = *(*I)->pred_begin();
243 ProgramPoint P = N->getLocation();
244
245 const ValueState* St = (*I)->getState();
246
247 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
248 if (PS->getStmt() == Ex)
249 St = N->getState();
250
251 FindUndefExpr FindIt(Eng.getStateManager(), St);
252 Ex = FindIt.FindExpr(Ex);
253
254 RangedBugReport R(*this, *I);
255 R.addRange(Ex->getSourceRange());
256
257 BR.EmitWarning(R);
258 }
259 }
260};
261
262//===----------------------------------------------------------------------===//
263// __attribute__(nonnull) checking
264
265class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
266 SimpleBugType BT;
267 std::list<RangedBugReport> Reports;
268
269public:
270 CheckAttrNonNull() :
271 BT("'nonnull' argument passed null",
272 "Null pointer passed as an argument to a 'nonnull' parameter") {}
273
274 virtual bool Audit(ExplodedNode<ValueState>* N, ValueStateManager& VMgr) {
275 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
276 const ValueState* state = N->getState();
277
278 RVal X = VMgr.GetRVal(state, CE->getCallee());
279
280 if (!isa<lval::FuncVal>(X))
281 return false;
282
283 FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<lval::FuncVal>(X).getDecl());
284 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
285
286 if (!Att)
287 return false;
288
289 // Iterate through the arguments of CE and check them for null.
290
291 unsigned idx = 0;
292 bool hasError = false;
293
294 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
295 ++I, ++idx) {
296
297 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
298 continue;
299
300 RangedBugReport R(BT, N);
301 R.addRange((*I)->getSourceRange());
302 Reports.push_back(R);
303 hasError = true;
304 }
305
306 return hasError;
307 }
308
309 virtual void EmitWarnings(BugReporter& BR) {
310 for (std::list<RangedBugReport>::iterator I=Reports.begin(),
311 E=Reports.end(); I!=E; ++I)
312 BR.EmitWarning(*I);
313 }
314};
315} // end anonymous namespace
316
317//===----------------------------------------------------------------------===//
318// Check registration.
319
320void GRExprEngine::RegisterInternalChecks() {
321 Register(new NullDeref());
322 Register(new UndefinedDeref());
323 Register(new UndefBranch());
324 Register(new DivZero());
325 Register(new UndefResult());
326 Register(new BadCall());
327 Register(new RetStack());
328 Register(new BadArg());
329 Register(new BadMsgExprArg());
330 Register(new BadReceiver());
331 AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
332}