blob: b4d4cb2c5686ce258b37fca3b358757ae59ee536 [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"
Ted Kremenek8aed8062008-10-31 00:13:20 +000017#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000018#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000019#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000020
21using namespace clang;
22
23//===----------------------------------------------------------------------===//
24// Utility functions.
25//===----------------------------------------------------------------------===//
26
27template <typename ITERATOR> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000028ExplodedNode<GRState>* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000029 return *I;
30}
31
32template <> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000033ExplodedNode<GRState>* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000034 return I->first;
35}
36
37//===----------------------------------------------------------------------===//
38// Bug Descriptions.
39//===----------------------------------------------------------------------===//
40
41namespace {
42class VISIBILITY_HIDDEN BuiltinBug : public BugTypeCacheLocation {
43 const char* name;
44 const char* desc;
45public:
Ted Kremenek22bda882008-07-31 20:31:27 +000046 BuiltinBug(const char* n, const char* d = 0) : name(n), desc(d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +000047 virtual const char* getName() const { return name; }
Ted Kremenek22bda882008-07-31 20:31:27 +000048 virtual const char* getDescription() const {
49 return desc ? desc : name;
50 }
51
Ted Kremenek78d46242008-07-22 16:21:24 +000052 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) = 0;
53 virtual void EmitWarnings(BugReporter& BR) {
54 EmitBuiltinWarnings(BR, cast<GRBugReporter>(BR).getEngine());
55 }
56
57 template <typename ITER>
58 void Emit(BugReporter& BR, ITER I, ITER E) {
59 for (; I != E; ++I) {
60 BugReport R(*this, GetNode(I));
61 BR.EmitWarning(R);
62 }
63 }
Ted Kremenek27133472008-09-21 18:57:28 +000064
65 virtual const char* getCategory() const { return "Logic Errors"; }
Ted Kremenek78d46242008-07-22 16:21:24 +000066};
67
68class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
69public:
70 NullDeref() : BuiltinBug("null dereference",
71 "Dereference of null pointer.") {}
72
73 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
74 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
75 }
76};
77
78class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
79public:
Ted Kremenek27133472008-09-21 18:57:28 +000080 UndefinedDeref() : BuiltinBug("uninitialized pointer dereference",
Ted Kremenek78d46242008-07-22 16:21:24 +000081 "Dereference of undefined value.") {}
82
83 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
84 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
85 }
86};
87
88class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
89public:
90 DivZero() : BuiltinBug("divide-by-zero",
91 "Division by zero/undefined value.") {}
92
93 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
94 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
95 }
96};
97
98class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
99public:
100 UndefResult() : BuiltinBug("undefined result",
101 "Result of operation is undefined.") {}
102
103 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
104 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
105 }
106};
107
108class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
109public:
110 BadCall()
111 : BuiltinBug("invalid function call",
112 "Called function is a NULL or undefined function pointer value.") {}
113
114 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
115 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
116 }
117};
118
119class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
120public:
Ted Kremenek27133472008-09-21 18:57:28 +0000121 BadArg() : BuiltinBug("uninitialized argument",
Ted Kremenek78d46242008-07-22 16:21:24 +0000122 "Pass-by-value argument in function is undefined.") {}
123
Ted Kremenek27133472008-09-21 18:57:28 +0000124 BadArg(const char* d) : BuiltinBug("uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000125
126 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
127 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
128 E = Eng.undef_arg_end(); I!=E; ++I) {
129
130 // Generate a report for this bug.
131 RangedBugReport report(*this, I->first);
132 report.addRange(I->second->getSourceRange());
133
134 // Emit the warning.
135 BR.EmitWarning(report);
136 }
137 }
138};
139
140class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
141public:
142 BadMsgExprArg()
143 : BadArg("Pass-by-value argument in message expression is undefined.") {}
144
145 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
146 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
147 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
148
149 // Generate a report for this bug.
150 RangedBugReport report(*this, I->first);
151 report.addRange(I->second->getSourceRange());
152
153 // Emit the warning.
154 BR.EmitWarning(report);
155 }
156 }
157};
158
159class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
160public:
161 BadReceiver()
Ted Kremenek27133472008-09-21 18:57:28 +0000162 : BuiltinBug("uninitialized receiver",
Ted Kremenek78d46242008-07-22 16:21:24 +0000163 "Receiver in message expression is an uninitialized value.") {}
164
165 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
166 for (GRExprEngine::UndefReceiversTy::iterator I=Eng.undef_receivers_begin(),
167 End = Eng.undef_receivers_end(); I!=End; ++I) {
168
169 // Generate a report for this bug.
170 RangedBugReport report(*this, *I);
171
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000172 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000173 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
174 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
175 assert (E && "Receiver cannot be NULL");
176 report.addRange(E->getSourceRange());
177
178 // Emit the warning.
179 BR.EmitWarning(report);
180 }
181 }
182};
Ted Kremenek5917d782008-11-21 00:27:44 +0000183
Ted Kremenek78d46242008-07-22 16:21:24 +0000184class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
185public:
Ted Kremenek22bda882008-07-31 20:31:27 +0000186 RetStack() : BuiltinBug("return of stack address") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000187
188 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000189 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
190 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000191
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000192 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000193 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
194 Expr* E = cast<ReturnStmt>(S)->getRetValue();
195 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000196
197 // Get the value associated with E.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000198 loc::MemRegionVal V =
199 cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
Ted Kremenek9e240492008-10-04 05:50:14 +0000200 E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000201
202 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000203 std::string buf;
204 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000205 SourceRange R;
Ted Kremenek22bda882008-07-31 20:31:27 +0000206
Ted Kremenek8aed8062008-10-31 00:13:20 +0000207 // Check if the region is a compound literal.
208 if (const CompoundLiteralRegion* CR =
209 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
210
211 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
212 os << "Address of stack memory associated with a compound literal "
213 "declared on line "
214 << BR.getSourceManager().getLogicalLineNumber(CL->getLocStart())
215 << " returned.";
216
217 R = CL->getSourceRange();
218 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000219 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
220 const Expr* ARE = AR->getExpr();
221 SourceLocation L = ARE->getLocStart();
222 R = ARE->getSourceRange();
223
224 os << "Address of stack memory allocated by call to alloca() on line "
225 << BR.getSourceManager().getLogicalLineNumber(L)
226 << " returned.";
227 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000228 else {
229 os << "Address of stack memory associated with local variable '"
230 << V.getRegion()->getString() << "' returned.";
231 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000232
Ted Kremenekad51a602008-10-31 00:18:30 +0000233 RangedBugReport report(*this, N, os.str().c_str());
Ted Kremenekb7714b22008-07-30 17:49:12 +0000234 report.addRange(E->getSourceRange());
Ted Kremenek8aed8062008-10-31 00:13:20 +0000235 if (R.isValid()) report.addRange(R);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000236
237 // Emit the warning.
238 BR.EmitWarning(report);
239 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000240 }
241};
Ted Kremenek5917d782008-11-21 00:27:44 +0000242
243class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
244public:
245 RetUndef() : BuiltinBug("uninitialized return value",
246 "Uninitialized or undefined return value returned to caller.") {}
247
248 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
249 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
250 }
251};
Ted Kremenek78d46242008-07-22 16:21:24 +0000252
253class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
254 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000255 GRStateManager& VM;
256 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000257
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000258 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000259
Ted Kremenekb7714b22008-07-30 17:49:12 +0000260 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000261 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000262 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000263
Ted Kremenekb7714b22008-07-30 17:49:12 +0000264 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000265 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
266 Expr* E2 = FindExpr(ExI);
267 if (E2) return E2;
268 }
269
270 return Ex;
271 }
272
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000273 bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000274 };
275
276public:
277 UndefBranch()
278 : BuiltinBug("uninitialized value",
279 "Branch condition evaluates to an uninitialized value.") {}
280
281 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
282 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
283 E=Eng.undef_branches_end(); I!=E; ++I) {
284
285 // What's going on here: we want to highlight the subexpression of the
286 // condition that is the most likely source of the "uninitialized
287 // branch condition." We do a recursive walk of the condition's
288 // subexpressions and roughly look for the most nested subexpression
289 // that binds to Undefined. We then highlight that expression's range.
290
291 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
292 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
293 assert (Ex && "Block must have a terminator.");
294
295 // Get the predecessor node and check if is a PostStmt with the Stmt
296 // being the terminator condition. We want to inspect the state
297 // of that node instead because it will contain main information about
298 // the subexpressions.
299
300 assert (!(*I)->pred_empty());
301
302 // Note: any predecessor will do. They should have identical state,
303 // since all the BlockEdge did was act as an error sink since the value
304 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000305 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000306 ProgramPoint P = N->getLocation();
307
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000308 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000309
310 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
311 if (PS->getStmt() == Ex)
312 St = N->getState();
313
314 FindUndefExpr FindIt(Eng.getStateManager(), St);
315 Ex = FindIt.FindExpr(Ex);
316
317 RangedBugReport R(*this, *I);
318 R.addRange(Ex->getSourceRange());
319
320 BR.EmitWarning(R);
321 }
322 }
323};
324
325//===----------------------------------------------------------------------===//
326// __attribute__(nonnull) checking
327
328class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
329 SimpleBugType BT;
330 std::list<RangedBugReport> Reports;
331
332public:
333 CheckAttrNonNull() :
Ted Kremenek8c036c72008-09-20 04:23:38 +0000334 BT("'nonnull' argument passed null", "API",
Ted Kremenek78d46242008-07-22 16:21:24 +0000335 "Null pointer passed as an argument to a 'nonnull' parameter") {}
336
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000337 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000338 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000339 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000340
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000341 SVal X = VMgr.GetSVal(state, CE->getCallee());
Ted Kremenek78d46242008-07-22 16:21:24 +0000342
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000343 if (!isa<loc::FuncVal>(X))
Ted Kremenek78d46242008-07-22 16:21:24 +0000344 return false;
345
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000346 FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<loc::FuncVal>(X).getDecl());
Ted Kremenek78d46242008-07-22 16:21:24 +0000347 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
348
349 if (!Att)
350 return false;
351
352 // Iterate through the arguments of CE and check them for null.
353
354 unsigned idx = 0;
355 bool hasError = false;
356
357 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
358 ++I, ++idx) {
359
360 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
361 continue;
362
363 RangedBugReport R(BT, N);
364 R.addRange((*I)->getSourceRange());
365 Reports.push_back(R);
366 hasError = true;
367 }
368
369 return hasError;
370 }
371
372 virtual void EmitWarnings(BugReporter& BR) {
373 for (std::list<RangedBugReport>::iterator I=Reports.begin(),
374 E=Reports.end(); I!=E; ++I)
375 BR.EmitWarning(*I);
376 }
377};
378} // end anonymous namespace
379
380//===----------------------------------------------------------------------===//
381// Check registration.
382
383void GRExprEngine::RegisterInternalChecks() {
384 Register(new NullDeref());
385 Register(new UndefinedDeref());
386 Register(new UndefBranch());
387 Register(new DivZero());
388 Register(new UndefResult());
389 Register(new BadCall());
390 Register(new RetStack());
Ted Kremenek5917d782008-11-21 00:27:44 +0000391 Register(new RetUndef());
Ted Kremenek78d46242008-07-22 16:21:24 +0000392 Register(new BadArg());
393 Register(new BadMsgExprArg());
394 Register(new BadReceiver());
395 AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
396}