blob: 853c6544e8310dd685c9ac5628d6d44dbb01959c [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) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000184 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
185 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
186
187 // Generate a report for this bug.
188 RangedBugReport report(*this, *I);
189
190 ExplodedNode<ValueState>* N = *I;
191 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
192 Expr* E = cast<ReturnStmt>(S)->getRetValue();
193 assert (E && "Return expression cannot be NULL");
194 report.addRange(E->getSourceRange());
195
196 // Emit the warning.
197 BR.EmitWarning(report);
198 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000199 }
200};
201
202
203class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
204 struct VISIBILITY_HIDDEN FindUndefExpr {
205 ValueStateManager& VM;
206 const ValueState* St;
207
208 FindUndefExpr(ValueStateManager& V, const ValueState* S) : VM(V), St(S) {}
209
Ted Kremenekb7714b22008-07-30 17:49:12 +0000210 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000211 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000212 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000213
Ted Kremenekb7714b22008-07-30 17:49:12 +0000214 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000215 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
216 Expr* E2 = FindExpr(ExI);
217 if (E2) return E2;
218 }
219
220 return Ex;
221 }
222
223 bool MatchesCriteria(Expr* Ex) { return VM.GetRVal(St, Ex).isUndef(); }
224 };
225
226public:
227 UndefBranch()
228 : BuiltinBug("uninitialized value",
229 "Branch condition evaluates to an uninitialized value.") {}
230
231 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
232 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
233 E=Eng.undef_branches_end(); I!=E; ++I) {
234
235 // What's going on here: we want to highlight the subexpression of the
236 // condition that is the most likely source of the "uninitialized
237 // branch condition." We do a recursive walk of the condition's
238 // subexpressions and roughly look for the most nested subexpression
239 // that binds to Undefined. We then highlight that expression's range.
240
241 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
242 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
243 assert (Ex && "Block must have a terminator.");
244
245 // Get the predecessor node and check if is a PostStmt with the Stmt
246 // being the terminator condition. We want to inspect the state
247 // of that node instead because it will contain main information about
248 // the subexpressions.
249
250 assert (!(*I)->pred_empty());
251
252 // Note: any predecessor will do. They should have identical state,
253 // since all the BlockEdge did was act as an error sink since the value
254 // had to already be undefined.
255 ExplodedNode<ValueState> *N = *(*I)->pred_begin();
256 ProgramPoint P = N->getLocation();
257
258 const ValueState* St = (*I)->getState();
259
260 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
261 if (PS->getStmt() == Ex)
262 St = N->getState();
263
264 FindUndefExpr FindIt(Eng.getStateManager(), St);
265 Ex = FindIt.FindExpr(Ex);
266
267 RangedBugReport R(*this, *I);
268 R.addRange(Ex->getSourceRange());
269
270 BR.EmitWarning(R);
271 }
272 }
273};
274
275//===----------------------------------------------------------------------===//
276// __attribute__(nonnull) checking
277
278class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
279 SimpleBugType BT;
280 std::list<RangedBugReport> Reports;
281
282public:
283 CheckAttrNonNull() :
284 BT("'nonnull' argument passed null",
285 "Null pointer passed as an argument to a 'nonnull' parameter") {}
286
287 virtual bool Audit(ExplodedNode<ValueState>* N, ValueStateManager& VMgr) {
288 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
289 const ValueState* state = N->getState();
290
291 RVal X = VMgr.GetRVal(state, CE->getCallee());
292
293 if (!isa<lval::FuncVal>(X))
294 return false;
295
296 FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<lval::FuncVal>(X).getDecl());
297 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
298
299 if (!Att)
300 return false;
301
302 // Iterate through the arguments of CE and check them for null.
303
304 unsigned idx = 0;
305 bool hasError = false;
306
307 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
308 ++I, ++idx) {
309
310 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
311 continue;
312
313 RangedBugReport R(BT, N);
314 R.addRange((*I)->getSourceRange());
315 Reports.push_back(R);
316 hasError = true;
317 }
318
319 return hasError;
320 }
321
322 virtual void EmitWarnings(BugReporter& BR) {
323 for (std::list<RangedBugReport>::iterator I=Reports.begin(),
324 E=Reports.end(); I!=E; ++I)
325 BR.EmitWarning(*I);
326 }
327};
328} // end anonymous namespace
329
330//===----------------------------------------------------------------------===//
331// Check registration.
332
333void GRExprEngine::RegisterInternalChecks() {
334 Register(new NullDeref());
335 Register(new UndefinedDeref());
336 Register(new UndefBranch());
337 Register(new DivZero());
338 Register(new UndefResult());
339 Register(new BadCall());
340 Register(new RetStack());
341 Register(new BadArg());
342 Register(new BadMsgExprArg());
343 Register(new BadReceiver());
344 AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
345}