blob: d61998c5a410f8adf0cb43b792c5c4fc9cf27476 [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"
Ted Kremenek22bda882008-07-31 20:31:27 +000018#include <sstream>
Ted Kremenek78d46242008-07-22 16:21:24 +000019
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
23// Utility functions.
24//===----------------------------------------------------------------------===//
25
26template <typename ITERATOR> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000027ExplodedNode<GRState>* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000028 return *I;
29}
30
31template <> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000032ExplodedNode<GRState>* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000033 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:
Ted Kremenek22bda882008-07-31 20:31:27 +000045 BuiltinBug(const char* n, const char* d = 0) : name(n), desc(d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +000046 virtual const char* getName() const { return name; }
Ted Kremenek22bda882008-07-31 20:31:27 +000047 virtual const char* getDescription() const {
48 return desc ? desc : name;
49 }
50
Ted Kremenek78d46242008-07-22 16:21:24 +000051 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) = 0;
52 virtual void EmitWarnings(BugReporter& BR) {
53 EmitBuiltinWarnings(BR, cast<GRBugReporter>(BR).getEngine());
54 }
55
56 template <typename ITER>
57 void Emit(BugReporter& BR, ITER I, ITER E) {
58 for (; I != E; ++I) {
59 BugReport R(*this, GetNode(I));
60 BR.EmitWarning(R);
61 }
62 }
Ted Kremenek27133472008-09-21 18:57:28 +000063
64 virtual const char* getCategory() const { return "Logic Errors"; }
Ted Kremenek78d46242008-07-22 16:21:24 +000065};
66
67class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
68public:
69 NullDeref() : BuiltinBug("null dereference",
70 "Dereference of null pointer.") {}
71
72 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
73 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
74 }
75};
76
77class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
78public:
Ted Kremenek27133472008-09-21 18:57:28 +000079 UndefinedDeref() : BuiltinBug("uninitialized pointer dereference",
Ted Kremenek78d46242008-07-22 16:21:24 +000080 "Dereference of undefined value.") {}
81
82 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
83 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
84 }
85};
86
87class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
88public:
89 DivZero() : BuiltinBug("divide-by-zero",
90 "Division by zero/undefined value.") {}
91
92 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
93 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
94 }
95};
96
97class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
98public:
99 UndefResult() : BuiltinBug("undefined result",
100 "Result of operation is undefined.") {}
101
102 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
103 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
104 }
105};
106
107class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
108public:
109 BadCall()
110 : BuiltinBug("invalid function call",
111 "Called function is a NULL or undefined function pointer value.") {}
112
113 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
114 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
115 }
116};
117
118class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
119public:
Ted Kremenek27133472008-09-21 18:57:28 +0000120 BadArg() : BuiltinBug("uninitialized argument",
Ted Kremenek78d46242008-07-22 16:21:24 +0000121 "Pass-by-value argument in function is undefined.") {}
122
Ted Kremenek27133472008-09-21 18:57:28 +0000123 BadArg(const char* d) : BuiltinBug("uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000124
125 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
126 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
127 E = Eng.undef_arg_end(); I!=E; ++I) {
128
129 // Generate a report for this bug.
130 RangedBugReport report(*this, I->first);
131 report.addRange(I->second->getSourceRange());
132
133 // Emit the warning.
134 BR.EmitWarning(report);
135 }
136 }
137};
138
139class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
140public:
141 BadMsgExprArg()
142 : BadArg("Pass-by-value argument in message expression is undefined.") {}
143
144 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
145 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
146 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
147
148 // Generate a report for this bug.
149 RangedBugReport report(*this, I->first);
150 report.addRange(I->second->getSourceRange());
151
152 // Emit the warning.
153 BR.EmitWarning(report);
154 }
155 }
156};
157
158class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
159public:
160 BadReceiver()
Ted Kremenek27133472008-09-21 18:57:28 +0000161 : BuiltinBug("uninitialized receiver",
Ted Kremenek78d46242008-07-22 16:21:24 +0000162 "Receiver in message expression is an uninitialized value.") {}
163
164 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
165 for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
166 End = Eng.undef_receivers_end(); I!=End; ++I) {
167
168 // Generate a report for this bug.
169 RangedBugReport report(*this, *I);
170
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000171 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000172 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
173 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
174 assert (E && "Receiver cannot be NULL");
175 report.addRange(E->getSourceRange());
176
177 // Emit the warning.
178 BR.EmitWarning(report);
179 }
180 }
181};
182
183class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
184public:
Ted Kremenek22bda882008-07-31 20:31:27 +0000185 RetStack() : BuiltinBug("return of stack address") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000186
187 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000188 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
189 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000190
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000191 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000192 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
193 Expr* E = cast<ReturnStmt>(S)->getRetValue();
194 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000195
196 // Get the value associated with E.
Ted Kremenek9e240492008-10-04 05:50:14 +0000197 lval::MemRegionVal V =
198 cast<lval::MemRegionVal>(Eng.getStateManager().GetRVal(N->getState(),
199 E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000200
201 // Generate a report for this bug.
202 std::ostringstream os;
203 os << "Address of stack memory associated with local variable '"
Ted Kremenek9e240492008-10-04 05:50:14 +0000204 << V.getRegion()->getString() << "' returned.";
Ted Kremenek22bda882008-07-31 20:31:27 +0000205
206 std::string s = os.str();
207
208 RangedBugReport report(*this, N, s.c_str());
Ted Kremenekb7714b22008-07-30 17:49:12 +0000209 report.addRange(E->getSourceRange());
210
211 // Emit the warning.
212 BR.EmitWarning(report);
213 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000214 }
215};
216
217
218class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
219 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000220 GRStateManager& VM;
221 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000222
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000223 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000224
Ted Kremenekb7714b22008-07-30 17:49:12 +0000225 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000226 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000227 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000228
Ted Kremenekb7714b22008-07-30 17:49:12 +0000229 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000230 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
231 Expr* E2 = FindExpr(ExI);
232 if (E2) return E2;
233 }
234
235 return Ex;
236 }
237
238 bool MatchesCriteria(Expr* Ex) { return VM.GetRVal(St, Ex).isUndef(); }
239 };
240
241public:
242 UndefBranch()
243 : BuiltinBug("uninitialized value",
244 "Branch condition evaluates to an uninitialized value.") {}
245
246 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
247 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
248 E=Eng.undef_branches_end(); I!=E; ++I) {
249
250 // What's going on here: we want to highlight the subexpression of the
251 // condition that is the most likely source of the "uninitialized
252 // branch condition." We do a recursive walk of the condition's
253 // subexpressions and roughly look for the most nested subexpression
254 // that binds to Undefined. We then highlight that expression's range.
255
256 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
257 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
258 assert (Ex && "Block must have a terminator.");
259
260 // Get the predecessor node and check if is a PostStmt with the Stmt
261 // being the terminator condition. We want to inspect the state
262 // of that node instead because it will contain main information about
263 // the subexpressions.
264
265 assert (!(*I)->pred_empty());
266
267 // Note: any predecessor will do. They should have identical state,
268 // since all the BlockEdge did was act as an error sink since the value
269 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000270 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000271 ProgramPoint P = N->getLocation();
272
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000273 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000274
275 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
276 if (PS->getStmt() == Ex)
277 St = N->getState();
278
279 FindUndefExpr FindIt(Eng.getStateManager(), St);
280 Ex = FindIt.FindExpr(Ex);
281
282 RangedBugReport R(*this, *I);
283 R.addRange(Ex->getSourceRange());
284
285 BR.EmitWarning(R);
286 }
287 }
288};
289
290//===----------------------------------------------------------------------===//
291// __attribute__(nonnull) checking
292
293class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
294 SimpleBugType BT;
295 std::list<RangedBugReport> Reports;
296
297public:
298 CheckAttrNonNull() :
Ted Kremenek8c036c72008-09-20 04:23:38 +0000299 BT("'nonnull' argument passed null", "API",
Ted Kremenek78d46242008-07-22 16:21:24 +0000300 "Null pointer passed as an argument to a 'nonnull' parameter") {}
301
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000302 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000303 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000304 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000305
306 RVal X = VMgr.GetRVal(state, CE->getCallee());
307
308 if (!isa<lval::FuncVal>(X))
309 return false;
310
311 FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<lval::FuncVal>(X).getDecl());
312 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
313
314 if (!Att)
315 return false;
316
317 // Iterate through the arguments of CE and check them for null.
318
319 unsigned idx = 0;
320 bool hasError = false;
321
322 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
323 ++I, ++idx) {
324
325 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
326 continue;
327
328 RangedBugReport R(BT, N);
329 R.addRange((*I)->getSourceRange());
330 Reports.push_back(R);
331 hasError = true;
332 }
333
334 return hasError;
335 }
336
337 virtual void EmitWarnings(BugReporter& BR) {
338 for (std::list<RangedBugReport>::iterator I=Reports.begin(),
339 E=Reports.end(); I!=E; ++I)
340 BR.EmitWarning(*I);
341 }
342};
343} // end anonymous namespace
344
345//===----------------------------------------------------------------------===//
346// Check registration.
347
348void GRExprEngine::RegisterInternalChecks() {
349 Register(new NullDeref());
350 Register(new UndefinedDeref());
351 Register(new UndefBranch());
352 Register(new DivZero());
353 Register(new UndefResult());
354 Register(new BadCall());
355 Register(new RetStack());
356 Register(new BadArg());
357 Register(new BadMsgExprArg());
358 Register(new BadReceiver());
359 AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
360}