blob: d32318ca7d91d4605ec93f2f4bed9b77e5cd62f3 [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 "
215 << BR.getSourceManager().getLogicalLineNumber(CL->getLocStart())
216 << " returned.";
217
218 R = CL->getSourceRange();
219 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000220 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
221 const Expr* ARE = AR->getExpr();
222 SourceLocation L = ARE->getLocStart();
223 R = ARE->getSourceRange();
224
225 os << "Address of stack memory allocated by call to alloca() on line "
226 << BR.getSourceManager().getLogicalLineNumber(L)
227 << " returned.";
228 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000229 else {
230 os << "Address of stack memory associated with local variable '"
231 << V.getRegion()->getString() << "' returned.";
232 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000233
Ted Kremenekad51a602008-10-31 00:18:30 +0000234 RangedBugReport report(*this, N, os.str().c_str());
Ted Kremenekb7714b22008-07-30 17:49:12 +0000235 report.addRange(E->getSourceRange());
Ted Kremenek8aed8062008-10-31 00:13:20 +0000236 if (R.isValid()) report.addRange(R);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000237
238 // Emit the warning.
239 BR.EmitWarning(report);
240 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000241 }
242};
Ted Kremenek5917d782008-11-21 00:27:44 +0000243
244class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
245public:
246 RetUndef() : BuiltinBug("uninitialized return value",
247 "Uninitialized or undefined return value returned to caller.") {}
248
249 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
250 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
251 }
252};
Ted Kremenek78d46242008-07-22 16:21:24 +0000253
254class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
255 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000256 GRStateManager& VM;
257 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000258
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000259 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000260
Ted Kremenekb7714b22008-07-30 17:49:12 +0000261 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000262 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000263 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000264
Ted Kremenekb7714b22008-07-30 17:49:12 +0000265 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000266 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
267 Expr* E2 = FindExpr(ExI);
268 if (E2) return E2;
269 }
270
271 return Ex;
272 }
273
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000274 bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000275 };
276
277public:
278 UndefBranch()
279 : BuiltinBug("uninitialized value",
280 "Branch condition evaluates to an uninitialized value.") {}
281
282 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
283 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
284 E=Eng.undef_branches_end(); I!=E; ++I) {
285
286 // What's going on here: we want to highlight the subexpression of the
287 // condition that is the most likely source of the "uninitialized
288 // branch condition." We do a recursive walk of the condition's
289 // subexpressions and roughly look for the most nested subexpression
290 // that binds to Undefined. We then highlight that expression's range.
291
292 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
293 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
294 assert (Ex && "Block must have a terminator.");
295
296 // Get the predecessor node and check if is a PostStmt with the Stmt
297 // being the terminator condition. We want to inspect the state
298 // of that node instead because it will contain main information about
299 // the subexpressions.
300
301 assert (!(*I)->pred_empty());
302
303 // Note: any predecessor will do. They should have identical state,
304 // since all the BlockEdge did was act as an error sink since the value
305 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000306 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000307 ProgramPoint P = N->getLocation();
308
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000309 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000310
311 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
312 if (PS->getStmt() == Ex)
313 St = N->getState();
314
315 FindUndefExpr FindIt(Eng.getStateManager(), St);
316 Ex = FindIt.FindExpr(Ex);
317
318 RangedBugReport R(*this, *I);
319 R.addRange(Ex->getSourceRange());
320
321 BR.EmitWarning(R);
322 }
323 }
324};
325
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000326class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
327public:
328 OutOfBoundMemoryAccess() : BuiltinBug("out-of-bound memory access",
329 "Load or store into an out-of-bound memory position.") {}
330
331 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
332 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
333 }
334};
Ted Kremenekefd59942008-12-08 22:47:34 +0000335
Ted Kremenek159d2482008-12-09 00:44:16 +0000336class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000337
338public:
Ted Kremenek159d2482008-12-09 00:44:16 +0000339 BadSizeVLA() : BuiltinBug("Zero-sized VLA",
Ted Kremenekefd59942008-12-08 22:47:34 +0000340 "VLAs with zero-size are undefined.") {}
341
342 virtual void EmitBuiltinWarnings(BugReporter& BR, GRExprEngine& Eng) {
343 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000344 I = Eng.ExplicitBadSizedVLA.begin(),
345 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
346
347 // Determine whether this was a 'zero-sized' VLA or a VLA with an
348 // undefined size.
349 GRExprEngine::NodeTy* N = *I;
350 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenekefd59942008-12-08 22:47:34 +0000351 DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
352 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
353 QualType T = Eng.getContext().getCanonicalType(VD->getType());
354 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000355 Expr* SizeExpr = VT->getSizeExpr();
Ted Kremenekefd59942008-12-08 22:47:34 +0000356
Ted Kremenek159d2482008-12-09 00:44:16 +0000357 std::string buf;
358 llvm::raw_string_ostream os(buf);
359 os << "The expression used to specify the number of elements in the VLA '"
360 << VD->getNameAsString() << "' evaluates to ";
361
362 SVal X = Eng.getStateManager().GetSVal(N->getState(), SizeExpr);
363 if (X.isUndef()) {
364 name = "Undefined size for VLA";
365 os << "an undefined or garbage value.";
366 }
367 else {
368 name = "Zero-sized VLA";
369 os << " to 0. VLAs with no elements have undefined behavior.";
370 }
371
372 desc = os.str().c_str();
373 RangedBugReport report(*this, N);
374 report.addRange(SizeExpr->getSourceRange());
Ted Kremenekefd59942008-12-08 22:47:34 +0000375
376 // Emit the warning.
377 BR.EmitWarning(report);
378 }
379 }
380};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000381
Ted Kremenek78d46242008-07-22 16:21:24 +0000382//===----------------------------------------------------------------------===//
383// __attribute__(nonnull) checking
384
385class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
386 SimpleBugType BT;
387 std::list<RangedBugReport> Reports;
388
389public:
390 CheckAttrNonNull() :
Ted Kremenek8c036c72008-09-20 04:23:38 +0000391 BT("'nonnull' argument passed null", "API",
Ted Kremenek78d46242008-07-22 16:21:24 +0000392 "Null pointer passed as an argument to a 'nonnull' parameter") {}
393
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000394 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000395 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000396 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000397
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000398 SVal X = VMgr.GetSVal(state, CE->getCallee());
Ted Kremenek78d46242008-07-22 16:21:24 +0000399
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000400 if (!isa<loc::FuncVal>(X))
Ted Kremenek78d46242008-07-22 16:21:24 +0000401 return false;
402
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000403 FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<loc::FuncVal>(X).getDecl());
Ted Kremenek78d46242008-07-22 16:21:24 +0000404 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
405
406 if (!Att)
407 return false;
408
409 // Iterate through the arguments of CE and check them for null.
410
411 unsigned idx = 0;
412 bool hasError = false;
413
414 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
415 ++I, ++idx) {
416
417 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
418 continue;
419
420 RangedBugReport R(BT, N);
421 R.addRange((*I)->getSourceRange());
422 Reports.push_back(R);
423 hasError = true;
424 }
425
426 return hasError;
427 }
428
429 virtual void EmitWarnings(BugReporter& BR) {
430 for (std::list<RangedBugReport>::iterator I=Reports.begin(),
431 E=Reports.end(); I!=E; ++I)
432 BR.EmitWarning(*I);
433 }
434};
435} // end anonymous namespace
436
437//===----------------------------------------------------------------------===//
438// Check registration.
439
440void GRExprEngine::RegisterInternalChecks() {
441 Register(new NullDeref());
442 Register(new UndefinedDeref());
443 Register(new UndefBranch());
444 Register(new DivZero());
445 Register(new UndefResult());
446 Register(new BadCall());
447 Register(new RetStack());
Ted Kremenek5917d782008-11-21 00:27:44 +0000448 Register(new RetUndef());
Ted Kremenek78d46242008-07-22 16:21:24 +0000449 Register(new BadArg());
450 Register(new BadMsgExprArg());
451 Register(new BadReceiver());
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000452 Register(new OutOfBoundMemoryAccess());
Ted Kremenek159d2482008-12-09 00:44:16 +0000453 Register(new BadSizeVLA());
Ted Kremenek78d46242008-07-22 16:21:24 +0000454 AddCheck(new CheckAttrNonNull(), Stmt::CallExprClass);
455}