blob: e7a644ce19e219b11e87f941dbb093e6a3e52838 [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 {
Ted Kremenek159d2482008-12-09 00:44:16 +000043protected:
Ted Kremenek78d46242008-07-22 16:21:24 +000044 const char* name;
45 const char* desc;
46public:
Ted Kremenek22bda882008-07-31 20:31:27 +000047 BuiltinBug(const char* n, const char* d = 0) : name(n), desc(d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +000048 virtual const char* getName() const { return name; }
Ted Kremenek22bda882008-07-31 20:31:27 +000049 virtual const char* getDescription() const {
50 return desc ? desc : name;
51 }
52
Ted Kremenek78d46242008-07-22 16:21:24 +000053 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) = 0;
54 virtual void EmitWarnings(BugReporter& BR) {
55 EmitBuiltinWarnings(BR, cast<GRBugReporter>(BR).getEngine());
56 }
57
58 template <typename ITER>
59 void Emit(BugReporter& BR, ITER I, ITER E) {
60 for (; I != E; ++I) {
61 BugReport R(*this, GetNode(I));
62 BR.EmitWarning(R);
63 }
64 }
Ted Kremenek27133472008-09-21 18:57:28 +000065
66 virtual const char* getCategory() const { return "Logic Errors"; }
Ted Kremenek78d46242008-07-22 16:21:24 +000067};
68
69class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
70public:
71 NullDeref() : BuiltinBug("null dereference",
72 "Dereference of null pointer.") {}
73
74 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
75 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
76 }
77};
78
79class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
80public:
Ted Kremenek27133472008-09-21 18:57:28 +000081 UndefinedDeref() : BuiltinBug("uninitialized pointer dereference",
Ted Kremenek78d46242008-07-22 16:21:24 +000082 "Dereference of undefined value.") {}
83
84 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
85 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
86 }
87};
88
89class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
90public:
91 DivZero() : BuiltinBug("divide-by-zero",
92 "Division by zero/undefined value.") {}
93
94 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
95 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
96 }
97};
98
99class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
100public:
101 UndefResult() : BuiltinBug("undefined result",
102 "Result of operation is undefined.") {}
103
104 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
105 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
106 }
107};
108
109class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
110public:
111 BadCall()
112 : BuiltinBug("invalid function call",
113 "Called function is a NULL or undefined function pointer value.") {}
114
115 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
116 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
117 }
118};
119
120class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
121public:
Ted Kremenek27133472008-09-21 18:57:28 +0000122 BadArg() : BuiltinBug("uninitialized argument",
Ted Kremenek78d46242008-07-22 16:21:24 +0000123 "Pass-by-value argument in function is undefined.") {}
124
Ted Kremenek27133472008-09-21 18:57:28 +0000125 BadArg(const char* d) : BuiltinBug("uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000126
127 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
128 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
129 E = Eng.undef_arg_end(); I!=E; ++I) {
130
131 // Generate a report for this bug.
132 RangedBugReport report(*this, I->first);
133 report.addRange(I->second->getSourceRange());
134
135 // Emit the warning.
136 BR.EmitWarning(report);
137 }
138 }
139};
140
141class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
142public:
143 BadMsgExprArg()
144 : BadArg("Pass-by-value argument in message expression is undefined.") {}
145
146 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
147 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
148 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
149
150 // Generate a report for this bug.
151 RangedBugReport report(*this, I->first);
152 report.addRange(I->second->getSourceRange());
153
154 // Emit the warning.
155 BR.EmitWarning(report);
156 }
157 }
158};
159
160class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
161public:
162 BadReceiver()
Ted Kremenek27133472008-09-21 18:57:28 +0000163 : BuiltinBug("uninitialized receiver",
Ted Kremenek78d46242008-07-22 16:21:24 +0000164 "Receiver in message expression is an uninitialized value.") {}
165
166 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000167 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000168 End = Eng.undef_receivers_end(); I!=End; ++I) {
169
170 // Generate a report for this bug.
171 RangedBugReport report(*this, *I);
172
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000173 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000174 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
175 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
176 assert (E && "Receiver cannot be NULL");
177 report.addRange(E->getSourceRange());
178
179 // Emit the warning.
180 BR.EmitWarning(report);
181 }
182 }
183};
Ted Kremenek5917d782008-11-21 00:27:44 +0000184
Ted Kremenek78d46242008-07-22 16:21:24 +0000185class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
186public:
Ted Kremenek22bda882008-07-31 20:31:27 +0000187 RetStack() : BuiltinBug("return of stack address") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000188
189 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000190 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
191 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000192
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000193 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000194 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
195 Expr* E = cast<ReturnStmt>(S)->getRetValue();
196 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000197
198 // Get the value associated with E.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000199 loc::MemRegionVal V =
200 cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
Ted Kremenek9e240492008-10-04 05:50:14 +0000201 E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000202
203 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000204 std::string buf;
205 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000206 SourceRange R;
Ted Kremenek22bda882008-07-31 20:31:27 +0000207
Ted Kremenek8aed8062008-10-31 00:13:20 +0000208 // Check if the region is a compound literal.
209 if (const CompoundLiteralRegion* CR =
210 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
211
212 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
213 os << "Address of stack memory associated with a compound literal "
214 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000215 << BR.getSourceManager()
216 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000217 << " returned.";
218
219 R = CL->getSourceRange();
220 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000221 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
222 const Expr* ARE = AR->getExpr();
223 SourceLocation L = ARE->getLocStart();
224 R = ARE->getSourceRange();
225
226 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000227 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000228 << " returned.";
229 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000230 else {
231 os << "Address of stack memory associated with local variable '"
232 << V.getRegion()->getString() << "' returned.";
233 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000234
Ted Kremenekad51a602008-10-31 00:18:30 +0000235 RangedBugReport report(*this, N, os.str().c_str());
Ted Kremenekb7714b22008-07-30 17:49:12 +0000236 report.addRange(E->getSourceRange());
Ted Kremenek8aed8062008-10-31 00:13:20 +0000237 if (R.isValid()) report.addRange(R);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000238
239 // Emit the warning.
240 BR.EmitWarning(report);
241 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000242 }
243};
Ted Kremenek5917d782008-11-21 00:27:44 +0000244
245class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
246public:
247 RetUndef() : BuiltinBug("uninitialized return value",
248 "Uninitialized or undefined return value returned to caller.") {}
249
250 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
251 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
252 }
253};
Ted Kremenek78d46242008-07-22 16:21:24 +0000254
255class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
256 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000257 GRStateManager& VM;
258 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000259
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000260 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000261
Ted Kremenekb7714b22008-07-30 17:49:12 +0000262 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000263 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000264 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000265
Ted Kremenekb7714b22008-07-30 17:49:12 +0000266 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000267 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
268 Expr* E2 = FindExpr(ExI);
269 if (E2) return E2;
270 }
271
272 return Ex;
273 }
274
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000275 bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000276 };
277
278public:
279 UndefBranch()
280 : BuiltinBug("uninitialized value",
281 "Branch condition evaluates to an uninitialized value.") {}
282
283 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
284 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
285 E=Eng.undef_branches_end(); I!=E; ++I) {
286
287 // What's going on here: we want to highlight the subexpression of the
288 // condition that is the most likely source of the "uninitialized
289 // branch condition." We do a recursive walk of the condition's
290 // subexpressions and roughly look for the most nested subexpression
291 // that binds to Undefined. We then highlight that expression's range.
292
293 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
294 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
295 assert (Ex && "Block must have a terminator.");
296
297 // Get the predecessor node and check if is a PostStmt with the Stmt
298 // being the terminator condition. We want to inspect the state
299 // of that node instead because it will contain main information about
300 // the subexpressions.
301
302 assert (!(*I)->pred_empty());
303
304 // Note: any predecessor will do. They should have identical state,
305 // since all the BlockEdge did was act as an error sink since the value
306 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000307 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000308 ProgramPoint P = N->getLocation();
309
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000310 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000311
312 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
313 if (PS->getStmt() == Ex)
314 St = N->getState();
315
316 FindUndefExpr FindIt(Eng.getStateManager(), St);
317 Ex = FindIt.FindExpr(Ex);
318
319 RangedBugReport R(*this, *I);
320 R.addRange(Ex->getSourceRange());
321
322 BR.EmitWarning(R);
323 }
324 }
325};
326
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000327class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
328public:
329 OutOfBoundMemoryAccess() : BuiltinBug("out-of-bound memory access",
330 "Load or store into an out-of-bound memory position.") {}
331
332 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
333 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
334 }
335};
Ted Kremenekefd59942008-12-08 22:47:34 +0000336
Ted Kremenek159d2482008-12-09 00:44:16 +0000337class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000338
339public:
Ted Kremenek159d2482008-12-09 00:44:16 +0000340 BadSizeVLA() : BuiltinBug("Zero-sized VLA",
Ted Kremenekefd59942008-12-08 22:47:34 +0000341 "VLAs with zero-size are undefined.") {}
342
343 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
344 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000345 I = Eng.ExplicitBadSizedVLA.begin(),
346 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
347
348 // Determine whether this was a 'zero-sized' VLA or a VLA with an
349 // undefined size.
350 GRExprEngine::NodeTy* N = *I;
351 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenekefd59942008-12-08 22:47:34 +0000352 DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
353 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
354 QualType T = Eng.getContext().getCanonicalType(VD->getType());
355 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000356 Expr* SizeExpr = VT->getSizeExpr();
Ted Kremenekefd59942008-12-08 22:47:34 +0000357
Ted Kremenek159d2482008-12-09 00:44:16 +0000358 std::string buf;
359 llvm::raw_string_ostream os(buf);
360 os << "The expression used to specify the number of elements in the VLA '"
361 << VD->getNameAsString() << "' evaluates to ";
362
363 SVal X = Eng.getStateManager().GetSVal(N->getState(), SizeExpr);
364 if (X.isUndef()) {
365 name = "Undefined size for VLA";
366 os << "an undefined or garbage value.";
367 }
368 else {
369 name = "Zero-sized VLA";
370 os << " to 0. VLAs with no elements have undefined behavior.";
371 }
372
373 desc = os.str().c_str();
374 RangedBugReport report(*this, N);
375 report.addRange(SizeExpr->getSourceRange());
Ted Kremenekefd59942008-12-08 22:47:34 +0000376
377 // Emit the warning.
378 BR.EmitWarning(report);
379 }
380 }
381};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000382
Ted Kremenek78d46242008-07-22 16:21:24 +0000383//===----------------------------------------------------------------------===//
384// __attribute__(nonnull) checking
385
386class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
387 SimpleBugType BT;
388 std::list<RangedBugReport> Reports;
389
390public:
391 CheckAttrNonNull() :
Ted Kremenek8c036c72008-09-20 04:23:38 +0000392 BT("'nonnull' argument passed null", "API",
Ted Kremenek78d46242008-07-22 16:21:24 +0000393 "Null pointer passed as an argument to a 'nonnull' parameter") {}
394
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000395 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000396 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000397 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000398
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000399 SVal X = VMgr.GetSVal(state, CE->getCallee());
Ted Kremenek78d46242008-07-22 16:21:24 +0000400
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000401 if (!isa<loc::FuncVal>(X))
Ted Kremenek78d46242008-07-22 16:21:24 +0000402 return false;
403
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000404 FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<loc::FuncVal>(X).getDecl());
Ted Kremenek78d46242008-07-22 16:21:24 +0000405 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
406
407 if (!Att)
408 return false;
409
410 // Iterate through the arguments of CE and check them for null.
411
412 unsigned idx = 0;
413 bool hasError = false;
414
415 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
416 ++I, ++idx) {
417
418 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
419 continue;
420
421 RangedBugReport R(BT, N);
422 R.addRange((*I)->getSourceRange());
423 Reports.push_back(R);
424 hasError = true;
425 }
426
427 return hasError;
428 }
429
430 virtual void EmitWarnings(BugReporter& BR) {
431 for (std::list<RangedBugReport>::iterator I=Reports.begin(),
432 E=Reports.end(); I!=E; ++I)
433 BR.EmitWarning(*I);
434 }
435};
436} // end anonymous namespace
437
438//===----------------------------------------------------------------------===//
439// Check registration.
440
441void GRExprEngine::RegisterInternalChecks() {
442 Register(new NullDeref());
443 Register(new UndefinedDeref());
444 Register(new UndefBranch());
445 Register(new DivZero());
446 Register(new UndefResult());
447 Register(new BadCall());
448 Register(new RetStack());
Ted Kremenek5917d782008-11-21 00:27:44 +0000449 Register(new RetUndef());
Ted Kremenek78d46242008-07-22 16:21:24 +0000450 Register(new BadArg());
451 Register(new BadMsgExprArg());
452 Register(new BadReceiver());
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000453 Register(new OutOfBoundMemoryAccess());
Ted Kremenek159d2482008-12-09 00:44:16 +0000454 Register(new BadSizeVLA());
Ted Kremenek78d46242008-07-22 16:21:24 +0000455 AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
456}