blob: 1b03149204188e13ee8ad5c3627c890b1d9daf1b [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 {
Ted Kremenekcf118d42009-02-04 23:49:09 +000042class VISIBILITY_HIDDEN BuiltinBug : public BugType {
43 GRExprEngine &Eng;
Ted Kremenek159d2482008-12-09 00:44:16 +000044protected:
Ted Kremenekcf118d42009-02-04 23:49:09 +000045 const std::string desc;
Ted Kremenek78d46242008-07-22 16:21:24 +000046public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000047 BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
48 : BugType(n, "Logic Errors"), Eng(*eng), desc(d) {}
49
50 BuiltinBug(GRExprEngine *eng, const char* n)
51 : BugType(n, "Logic Errors"), Eng(*eng), desc(n) {}
Ted Kremenek22bda882008-07-31 20:31:27 +000052
Ted Kremenekcf118d42009-02-04 23:49:09 +000053 virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) = 0;
54
55 void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
Ted Kremenek78d46242008-07-22 16:21:24 +000056
57 template <typename ITER>
58 void Emit(BugReporter& BR, ITER I, ITER E) {
Ted Kremenekcf118d42009-02-04 23:49:09 +000059 for (; I != E; ++I) BR.EmitReport(new BugReport(*this, desc.c_str(),
60 GetNode(I)));
61 }
Ted Kremenek78d46242008-07-22 16:21:24 +000062};
63
64class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
65public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000066 NullDeref(GRExprEngine* eng)
Ted Kremenek0fa96542009-04-07 04:54:31 +000067 : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
Ted Kremenek78d46242008-07-22 16:21:24 +000068
Ted Kremenekcf118d42009-02-04 23:49:09 +000069 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +000070 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
71 }
72};
73
Ted Kremenek21fe8372009-02-19 04:06:22 +000074class VISIBILITY_HIDDEN NilReceiverStructRet : public BugType {
75 GRExprEngine &Eng;
76public:
77 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek5d88ff82009-04-02 02:40:26 +000078 BugType("'nil' receiver with struct return type", "Logic Errors"),
Ted Kremenek21fe8372009-02-19 04:06:22 +000079 Eng(*eng) {}
80
81 void FlushReports(BugReporter& BR) {
82 for (GRExprEngine::nil_receiver_struct_ret_iterator
83 I=Eng.nil_receiver_struct_ret_begin(),
84 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
85
86 std::string sbuf;
87 llvm::raw_string_ostream os(sbuf);
88 PostStmt P = cast<PostStmt>((*I)->getLocation());
89 ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
90 os << "The receiver in the message expression is 'nil' and results in the"
91 " returned value (of type '"
92 << ME->getType().getAsString()
93 << "') to be garbage or otherwise undefined.";
94
95 RangedBugReport *R = new RangedBugReport(*this, os.str().c_str(), *I);
96 R->addRange(ME->getReceiver()->getSourceRange());
97 BR.EmitReport(R);
98 }
99 }
100};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000101
102class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BugType {
103 GRExprEngine &Eng;
104public:
105 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
106 BugType("'nil' receiver with return type larger than sizeof(void *)",
107 "Logic Errors"),
108 Eng(*eng) {}
109
110 void FlushReports(BugReporter& BR) {
111 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
112 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
113 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
114
115 std::string sbuf;
116 llvm::raw_string_ostream os(sbuf);
117 PostStmt P = cast<PostStmt>((*I)->getLocation());
118 ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
119 os << "The receiver in the message expression is 'nil' and results in the"
120 " returned value (of type '"
121 << ME->getType().getAsString()
122 << "' and of size "
123 << Eng.getContext().getTypeSize(ME->getType()) / 8
124 << " bytes) to be garbage or otherwise undefined.";
125
126 RangedBugReport *R = new RangedBugReport(*this, os.str().c_str(), *I);
127 R->addRange(ME->getReceiver()->getSourceRange());
128 BR.EmitReport(R);
129 }
130 }
131};
Ted Kremenek21fe8372009-02-19 04:06:22 +0000132
Ted Kremenek78d46242008-07-22 16:21:24 +0000133class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
134public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000135 UndefinedDeref(GRExprEngine* eng)
Ted Kremenek17a8e072009-03-01 05:43:22 +0000136 : BuiltinBug(eng,"Dereference of undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000137
Ted Kremenekcf118d42009-02-04 23:49:09 +0000138 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000139 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
140 }
141};
142
143class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
144public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000145 DivZero(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000146 : BuiltinBug(eng,"Division-by-zero",
147 "Division by zero or undefined value.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000148
Ted Kremenekcf118d42009-02-04 23:49:09 +0000149 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000150 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
151 }
152};
153
154class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
155public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000156 UndefResult(GRExprEngine* eng) : BuiltinBug(eng,"Undefined result",
Ted Kremenek78d46242008-07-22 16:21:24 +0000157 "Result of operation is undefined.") {}
158
Ted Kremenekcf118d42009-02-04 23:49:09 +0000159 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000160 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
161 }
162};
163
164class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
165public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000166 BadCall(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000167 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000168 "Called function pointer is a null or undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000169
Ted Kremenekcf118d42009-02-04 23:49:09 +0000170 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000171 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
172 }
173};
174
175class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
176public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000177 BadArg(GRExprEngine* eng) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000178 "Pass-by-value argument in function call is undefined.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000179
Ted Kremenekcf118d42009-02-04 23:49:09 +0000180 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000181 : BuiltinBug(eng,"Uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000182
Ted Kremenekcf118d42009-02-04 23:49:09 +0000183 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000184 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
185 E = Eng.undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000186 // Generate a report for this bug.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000187 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(),
188 I->first);
189 report->addRange(I->second->getSourceRange());
190 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000191 }
192 }
193};
194
195class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
196public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000197 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000198 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Ted Kremenek78d46242008-07-22 16:21:24 +0000199
Ted Kremenekcf118d42009-02-04 23:49:09 +0000200 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000201 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Ted Kremenekcf118d42009-02-04 23:49:09 +0000202 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000203 // Generate a report for this bug.
Ted Kremenek21fe8372009-02-19 04:06:22 +0000204 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(),
205 I->first);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000206 report->addRange(I->second->getSourceRange());
207 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000208 }
209 }
210};
211
212class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
213public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000214 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000215 : BuiltinBug(eng,"Uninitialized receiver",
216 "Receiver in message expression is an uninitialized value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000217
Ted Kremenekcf118d42009-02-04 23:49:09 +0000218 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000219 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000220 End = Eng.undef_receivers_end(); I!=End; ++I) {
221
222 // Generate a report for this bug.
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000223 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(), *I);
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000224 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000225 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
226 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
227 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000228 report->addRange(E->getSourceRange());
229 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000230 }
231 }
232};
Ted Kremenek5917d782008-11-21 00:27:44 +0000233
Ted Kremenek78d46242008-07-22 16:21:24 +0000234class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
235public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000236 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000237 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000238
Ted Kremenekcf118d42009-02-04 23:49:09 +0000239 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000240 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
241 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000242
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000243 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000244 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
245 Expr* E = cast<ReturnStmt>(S)->getRetValue();
246 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000247
248 // Get the value associated with E.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000249 loc::MemRegionVal V =
250 cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
Ted Kremenek9e240492008-10-04 05:50:14 +0000251 E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000252
253 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000254 std::string buf;
255 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000256 SourceRange R;
Ted Kremenek22bda882008-07-31 20:31:27 +0000257
Ted Kremenek8aed8062008-10-31 00:13:20 +0000258 // Check if the region is a compound literal.
259 if (const CompoundLiteralRegion* CR =
260 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
261
262 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
263 os << "Address of stack memory associated with a compound literal "
264 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000265 << BR.getSourceManager()
266 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000267 << " returned.";
268
269 R = CL->getSourceRange();
270 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000271 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
272 const Expr* ARE = AR->getExpr();
273 SourceLocation L = ARE->getLocStart();
274 R = ARE->getSourceRange();
275
276 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000277 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000278 << " returned.";
279 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000280 else {
281 os << "Address of stack memory associated with local variable '"
282 << V.getRegion()->getString() << "' returned.";
283 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000284
Ted Kremenekcf118d42009-02-04 23:49:09 +0000285 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
286 report->addRange(E->getSourceRange());
287 if (R.isValid()) report->addRange(R);
288 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000289 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000290 }
291};
Ted Kremenek5917d782008-11-21 00:27:44 +0000292
293class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
294public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000295 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Uninitialized return value",
Ted Kremenek5917d782008-11-21 00:27:44 +0000296 "Uninitialized or undefined return value returned to caller.") {}
297
Ted Kremenekcf118d42009-02-04 23:49:09 +0000298 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000299 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
300 }
301};
Ted Kremenek78d46242008-07-22 16:21:24 +0000302
303class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
304 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000305 GRStateManager& VM;
306 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000307
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000308 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000309
Ted Kremenekb7714b22008-07-30 17:49:12 +0000310 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000311 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000312 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000313
Ted Kremenekb7714b22008-07-30 17:49:12 +0000314 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000315 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
316 Expr* E2 = FindExpr(ExI);
317 if (E2) return E2;
318 }
319
320 return Ex;
321 }
322
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000323 bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000324 };
325
326public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000327 UndefBranch(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000328 : BuiltinBug(eng,"Use of uninitialized value",
Ted Kremenek78d46242008-07-22 16:21:24 +0000329 "Branch condition evaluates to an uninitialized value.") {}
330
Ted Kremenekcf118d42009-02-04 23:49:09 +0000331 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000332 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
333 E=Eng.undef_branches_end(); I!=E; ++I) {
334
335 // What's going on here: we want to highlight the subexpression of the
336 // condition that is the most likely source of the "uninitialized
337 // branch condition." We do a recursive walk of the condition's
338 // subexpressions and roughly look for the most nested subexpression
339 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000340 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
341 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
342 assert (Ex && "Block must have a terminator.");
343
344 // Get the predecessor node and check if is a PostStmt with the Stmt
345 // being the terminator condition. We want to inspect the state
346 // of that node instead because it will contain main information about
347 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000348 assert (!(*I)->pred_empty());
349
350 // Note: any predecessor will do. They should have identical state,
351 // since all the BlockEdge did was act as an error sink since the value
352 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000353 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000354 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000355 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000356
357 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
358 if (PS->getStmt() == Ex)
359 St = N->getState();
360
361 FindUndefExpr FindIt(Eng.getStateManager(), St);
362 Ex = FindIt.FindExpr(Ex);
363
Ted Kremenekcf118d42009-02-04 23:49:09 +0000364 RangedBugReport *R = new RangedBugReport(*this, desc.c_str(), *I);
365 R->addRange(Ex->getSourceRange());
366 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000367 }
368 }
369};
370
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000371class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
372public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000373 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000374 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000375 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000376
Ted Kremenekcf118d42009-02-04 23:49:09 +0000377 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000378 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
379 }
380};
Ted Kremenekefd59942008-12-08 22:47:34 +0000381
Ted Kremenek159d2482008-12-09 00:44:16 +0000382class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000383public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000384 BadSizeVLA(GRExprEngine* eng) :
385 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Ted Kremenekefd59942008-12-08 22:47:34 +0000386
Ted Kremenekcf118d42009-02-04 23:49:09 +0000387 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000388 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000389 I = Eng.ExplicitBadSizedVLA.begin(),
390 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
391
392 // Determine whether this was a 'zero-sized' VLA or a VLA with an
393 // undefined size.
394 GRExprEngine::NodeTy* N = *I;
395 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenekefd59942008-12-08 22:47:34 +0000396 DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
397 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
398 QualType T = Eng.getContext().getCanonicalType(VD->getType());
399 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000400 Expr* SizeExpr = VT->getSizeExpr();
Ted Kremenekefd59942008-12-08 22:47:34 +0000401
Ted Kremenek159d2482008-12-09 00:44:16 +0000402 std::string buf;
403 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000404 os << "The expression used to specify the number of elements in the "
405 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000406 << VD->getNameAsString() << "' evaluates to ";
Ted Kremenek159d2482008-12-09 00:44:16 +0000407
Ted Kremenekcf118d42009-02-04 23:49:09 +0000408 if (Eng.getStateManager().GetSVal(N->getState(), SizeExpr).isUndef())
Ted Kremenek159d2482008-12-09 00:44:16 +0000409 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000410 else
411 os << "0. VLAs with no elements have undefined behavior.";
Ted Kremenek159d2482008-12-09 00:44:16 +0000412
Ted Kremenekcf118d42009-02-04 23:49:09 +0000413 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
414 report->addRange(SizeExpr->getSourceRange());
415 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000416 }
417 }
418};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000419
Ted Kremenek78d46242008-07-22 16:21:24 +0000420//===----------------------------------------------------------------------===//
421// __attribute__(nonnull) checking
422
423class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000424 BugType *BT;
425 BugReporter &BR;
Ted Kremenek78d46242008-07-22 16:21:24 +0000426
427public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000428 CheckAttrNonNull(BugReporter &br) : BT(0), BR(br) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000429
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000430 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000431 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000432 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000433
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000434 SVal X = VMgr.GetSVal(state, CE->getCallee());
Zhongxing Xu369f4472009-04-20 05:24:46 +0000435
436 const FunctionDecl* FD = X.getAsFunctionDecl();
437 if (!FD)
Ted Kremenek78d46242008-07-22 16:21:24 +0000438 return false;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000439
Ted Kremenek78d46242008-07-22 16:21:24 +0000440 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
441
442 if (!Att)
443 return false;
444
445 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000446 unsigned idx = 0;
447 bool hasError = false;
448
449 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
450 ++I, ++idx) {
451
452 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
453 continue;
Ted Kremenekcf118d42009-02-04 23:49:09 +0000454
455 // Lazily allocate the BugType object if it hasn't already been created.
456 // Ownership is transferred to the BugReporter object once the BugReport
457 // is passed to 'EmitWarning'.
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000458 if (!BT) BT =
459 new BugType("Argument with 'nonnull' attribute passed null", "API");
Ted Kremenek78d46242008-07-22 16:21:24 +0000460
Ted Kremenekcf118d42009-02-04 23:49:09 +0000461 RangedBugReport *R = new RangedBugReport(*BT,
462 "Null pointer passed as an argument to a "
463 "'nonnull' parameter", N);
464
465 R->addRange((*I)->getSourceRange());
466 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000467 hasError = true;
468 }
469
470 return hasError;
471 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000472};
473} // end anonymous namespace
474
475//===----------------------------------------------------------------------===//
476// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000477//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000478
479void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000480 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
481 // are different than what probably many checks will do since they don't
482 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
483 // analyzing a function. Generation of BugReport objects is done via a call
484 // to 'FlushReports' from BugReporter.
485 BR.Register(new NullDeref(this));
486 BR.Register(new UndefinedDeref(this));
487 BR.Register(new UndefBranch(this));
488 BR.Register(new DivZero(this));
489 BR.Register(new UndefResult(this));
490 BR.Register(new BadCall(this));
491 BR.Register(new RetStack(this));
492 BR.Register(new RetUndef(this));
493 BR.Register(new BadArg(this));
494 BR.Register(new BadMsgExprArg(this));
495 BR.Register(new BadReceiver(this));
496 BR.Register(new OutOfBoundMemoryAccess(this));
497 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000498 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000499 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000500
501 // The following checks do not need to have their associated BugTypes
502 // explicitly registered with the BugReporter. If they issue any BugReports,
503 // their associated BugType will get registered with the BugReporter
504 // automatically. Note that the check itself is owned by the GRExprEngine
505 // object.
506 AddCheck(new CheckAttrNonNull(BR), Stmt::CallExprClass);
Ted Kremenek78d46242008-07-22 16:21:24 +0000507}