blob: aff58df42d646a5874a765b54bbb1a19dc1453c7 [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 Kremenekdd986cc2009-05-07 00:45:33 +000017#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000018#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000019#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000020#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000021
22using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000023using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000024
25//===----------------------------------------------------------------------===//
26// Utility functions.
27//===----------------------------------------------------------------------===//
28
29template <typename ITERATOR> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000030ExplodedNode<GRState>* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000031 return *I;
32}
33
34template <> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000035ExplodedNode<GRState>* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000036 return I->first;
37}
38
39//===----------------------------------------------------------------------===//
40// Bug Descriptions.
41//===----------------------------------------------------------------------===//
42
43namespace {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000044
Ted Kremenek0c313172009-05-13 19:16:35 +000045class VISIBILITY_HIDDEN BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000046public:
47 BuiltinBugReport(BugType& bt, const char* desc,
Ted Kremenek0c313172009-05-13 19:16:35 +000048 ExplodedNode<GRState> *n)
49 : RangedBugReport(bt, desc, n) {}
Ted Kremenekdd986cc2009-05-07 00:45:33 +000050
Ted Kremenek85ac9342009-05-15 05:25:09 +000051 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
52 ExplodedNode<GRState> *n)
53 : RangedBugReport(bt, shortDesc, desc, n) {}
54
Ted Kremenekdd986cc2009-05-07 00:45:33 +000055 void registerInitialVisitors(BugReporterContext& BRC,
56 const ExplodedNode<GRState>* N);
57};
58
Ted Kremenekcf118d42009-02-04 23:49:09 +000059class VISIBILITY_HIDDEN BuiltinBug : public BugType {
60 GRExprEngine &Eng;
Ted Kremenek159d2482008-12-09 00:44:16 +000061protected:
Ted Kremenekcf118d42009-02-04 23:49:09 +000062 const std::string desc;
Ted Kremenek78d46242008-07-22 16:21:24 +000063public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000064 BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
Ted Kremenek0c313172009-05-13 19:16:35 +000065 : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
Ted Kremenekcf118d42009-02-04 23:49:09 +000066
67 BuiltinBug(GRExprEngine *eng, const char* n)
Ted Kremenek0c313172009-05-13 19:16:35 +000068 : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
Ted Kremenek22bda882008-07-31 20:31:27 +000069
Ted Kremenekcf118d42009-02-04 23:49:09 +000070 virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) = 0;
71
72 void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
Ted Kremenek78d46242008-07-22 16:21:24 +000073
Ted Kremenekdd986cc2009-05-07 00:45:33 +000074 virtual void registerInitialVisitors(BugReporterContext& BRC,
75 const ExplodedNode<GRState>* N,
76 BuiltinBugReport *R) {}
77
78 template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
Ted Kremenek78d46242008-07-22 16:21:24 +000079};
80
Ted Kremenekdd986cc2009-05-07 00:45:33 +000081
82template <typename ITER>
83void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
84 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
85 GetNode(I)));
86}
87
88void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
89 const ExplodedNode<GRState>* N) {
90 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
91}
92
Ted Kremenek78d46242008-07-22 16:21:24 +000093class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
94public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000095 NullDeref(GRExprEngine* eng)
Ted Kremenek0fa96542009-04-07 04:54:31 +000096 : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
Ted Kremenek78d46242008-07-22 16:21:24 +000097
Ted Kremenekcf118d42009-02-04 23:49:09 +000098 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +000099 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
100 }
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000101
102 void registerInitialVisitors(BugReporterContext& BRC,
103 const ExplodedNode<GRState>* N,
104 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000105 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000106 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000107};
108
Ted Kremenek0c313172009-05-13 19:16:35 +0000109class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +0000110public:
111 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000112 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +0000113
Ted Kremenek0c313172009-05-13 19:16:35 +0000114 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +0000115 for (GRExprEngine::nil_receiver_struct_ret_iterator
116 I=Eng.nil_receiver_struct_ret_begin(),
117 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
118
119 std::string sbuf;
120 llvm::raw_string_ostream os(sbuf);
121 PostStmt P = cast<PostStmt>((*I)->getLocation());
122 ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
123 os << "The receiver in the message expression is 'nil' and results in the"
124 " returned value (of type '"
125 << ME->getType().getAsString()
126 << "') to be garbage or otherwise undefined.";
127
Ted Kremenek0c313172009-05-13 19:16:35 +0000128 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +0000129 R->addRange(ME->getReceiver()->getSourceRange());
130 BR.EmitReport(R);
131 }
132 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000133
134 void registerInitialVisitors(BugReporterContext& BRC,
135 const ExplodedNode<GRState>* N,
136 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000137 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000138 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000139};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000140
Ted Kremenek0c313172009-05-13 19:16:35 +0000141class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000142public:
143 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000144 BuiltinBug(eng,
145 "'nil' receiver with return type larger than sizeof(void *)") {}
Ted Kremenek899b3de2009-04-08 03:07:17 +0000146
Ted Kremenek0c313172009-05-13 19:16:35 +0000147 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000148 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
149 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
150 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
151
152 std::string sbuf;
153 llvm::raw_string_ostream os(sbuf);
154 PostStmt P = cast<PostStmt>((*I)->getLocation());
155 ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
156 os << "The receiver in the message expression is 'nil' and results in the"
157 " returned value (of type '"
158 << ME->getType().getAsString()
159 << "' and of size "
160 << Eng.getContext().getTypeSize(ME->getType()) / 8
161 << " bytes) to be garbage or otherwise undefined.";
162
Ted Kremenek0c313172009-05-13 19:16:35 +0000163 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000164 R->addRange(ME->getReceiver()->getSourceRange());
165 BR.EmitReport(R);
166 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000167 }
168 void registerInitialVisitors(BugReporterContext& BRC,
169 const ExplodedNode<GRState>* N,
170 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000171 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000172 }
173};
Ted Kremenek21fe8372009-02-19 04:06:22 +0000174
Ted Kremenek78d46242008-07-22 16:21:24 +0000175class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
176public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000177 UndefinedDeref(GRExprEngine* eng)
Ted Kremenek17a8e072009-03-01 05:43:22 +0000178 : BuiltinBug(eng,"Dereference of undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000179
Ted Kremenekcf118d42009-02-04 23:49:09 +0000180 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000181 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
182 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000183
184 void registerInitialVisitors(BugReporterContext& BRC,
185 const ExplodedNode<GRState>* N,
186 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000187 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000188 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000189};
190
191class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
192public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000193 DivZero(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000194 : BuiltinBug(eng,"Division-by-zero",
195 "Division by zero or undefined value.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000196
Ted Kremenekcf118d42009-02-04 23:49:09 +0000197 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000198 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
199 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000200
201 void registerInitialVisitors(BugReporterContext& BRC,
202 const ExplodedNode<GRState>* N,
203 BuiltinBugReport *R) {
204 registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
205 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000206};
207
208class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
209public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000210 UndefResult(GRExprEngine* eng) : BuiltinBug(eng,"Undefined result",
Ted Kremenek78d46242008-07-22 16:21:24 +0000211 "Result of operation is undefined.") {}
212
Ted Kremenekcf118d42009-02-04 23:49:09 +0000213 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000214 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
215 }
216};
217
218class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
219public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000220 BadCall(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000221 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000222 "Called function pointer is a null or undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000223
Ted Kremenekcf118d42009-02-04 23:49:09 +0000224 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000225 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
226 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000227
228 void registerInitialVisitors(BugReporterContext& BRC,
229 const ExplodedNode<GRState>* N,
230 BuiltinBugReport *R) {
231 registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
232 }
233};
234
235
236class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
237 const Stmt *Arg;
238public:
239 ArgReport(BugType& bt, const char* desc, ExplodedNode<GRState> *n,
240 const Stmt *arg)
241 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
242
243 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
244 ExplodedNode<GRState> *n, const Stmt *arg)
245 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
246
247 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000248};
249
250class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000251public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000252 BadArg(GRExprEngine* eng) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000253 "Pass-by-value argument in function call is undefined.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000254
Ted Kremenekcf118d42009-02-04 23:49:09 +0000255 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000256 : BuiltinBug(eng,"Uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000257
Ted Kremenekcf118d42009-02-04 23:49:09 +0000258 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000259 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
260 E = Eng.undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000261 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000262 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
263 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000264 report->addRange(I->second->getSourceRange());
265 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000266 }
267 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000268
269 void registerInitialVisitors(BugReporterContext& BRC,
270 const ExplodedNode<GRState>* N,
271 BuiltinBugReport *R) {
272 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
273 N);
274 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000275};
276
277class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
278public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000279 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000280 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Ted Kremenek78d46242008-07-22 16:21:24 +0000281
Ted Kremenekcf118d42009-02-04 23:49:09 +0000282 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000283 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Ted Kremenekcf118d42009-02-04 23:49:09 +0000284 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000285 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000286 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
287 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000288 report->addRange(I->second->getSourceRange());
289 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000290 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000291 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000292};
293
294class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
295public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000296 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000297 : BuiltinBug(eng,"Uninitialized receiver",
298 "Receiver in message expression is an uninitialized value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000299
Ted Kremenekcf118d42009-02-04 23:49:09 +0000300 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000301 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000302 End = Eng.undef_receivers_end(); I!=End; ++I) {
303
304 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000305 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000306 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000307 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
308 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
309 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000310 report->addRange(E->getSourceRange());
311 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000312 }
313 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000314
Ted Kremenek0c313172009-05-13 19:16:35 +0000315 void registerInitialVisitors(BugReporterContext& BRC,
316 const ExplodedNode<GRState>* N,
317 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000318 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
319 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000320};
Ted Kremenek5917d782008-11-21 00:27:44 +0000321
Ted Kremenek78d46242008-07-22 16:21:24 +0000322class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
323public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000324 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000325 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000326
Ted Kremenekcf118d42009-02-04 23:49:09 +0000327 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000328 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
329 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000330
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000331 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000332 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
333 Expr* E = cast<ReturnStmt>(S)->getRetValue();
334 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000335
336 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000337 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000338
339 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000340 std::string buf;
341 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000342 SourceRange R;
Ted Kremenek22bda882008-07-31 20:31:27 +0000343
Ted Kremenek8aed8062008-10-31 00:13:20 +0000344 // Check if the region is a compound literal.
345 if (const CompoundLiteralRegion* CR =
346 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
347
348 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
349 os << "Address of stack memory associated with a compound literal "
350 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000351 << BR.getSourceManager()
352 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000353 << " returned.";
354
355 R = CL->getSourceRange();
356 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000357 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
358 const Expr* ARE = AR->getExpr();
359 SourceLocation L = ARE->getLocStart();
360 R = ARE->getSourceRange();
361
362 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000363 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000364 << " returned.";
365 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000366 else {
367 os << "Address of stack memory associated with local variable '"
368 << V.getRegion()->getString() << "' returned.";
369 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000370
Ted Kremenekcf118d42009-02-04 23:49:09 +0000371 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
372 report->addRange(E->getSourceRange());
373 if (R.isValid()) report->addRange(R);
374 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000375 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000376 }
377};
Ted Kremenek5917d782008-11-21 00:27:44 +0000378
379class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
380public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000381 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Uninitialized return value",
Ted Kremenek0c313172009-05-13 19:16:35 +0000382 "Uninitialized or undefined value returned to caller.") {}
Ted Kremenek5917d782008-11-21 00:27:44 +0000383
Ted Kremenekcf118d42009-02-04 23:49:09 +0000384 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000385 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
386 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000387
388 void registerInitialVisitors(BugReporterContext& BRC,
389 const ExplodedNode<GRState>* N,
390 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000391 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
392 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000393};
Ted Kremenek78d46242008-07-22 16:21:24 +0000394
395class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
396 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000397 GRStateManager& VM;
398 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000399
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000400 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000401
Ted Kremenekb7714b22008-07-30 17:49:12 +0000402 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000403 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000404 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000405
Ted Kremenekb7714b22008-07-30 17:49:12 +0000406 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000407 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
408 Expr* E2 = FindExpr(ExI);
409 if (E2) return E2;
410 }
411
412 return Ex;
413 }
414
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000415 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000416 };
417
418public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000419 UndefBranch(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000420 : BuiltinBug(eng,"Use of uninitialized value",
Ted Kremenek78d46242008-07-22 16:21:24 +0000421 "Branch condition evaluates to an uninitialized value.") {}
422
Ted Kremenekcf118d42009-02-04 23:49:09 +0000423 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000424 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
425 E=Eng.undef_branches_end(); I!=E; ++I) {
426
427 // What's going on here: we want to highlight the subexpression of the
428 // condition that is the most likely source of the "uninitialized
429 // branch condition." We do a recursive walk of the condition's
430 // subexpressions and roughly look for the most nested subexpression
431 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000432 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
433 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
434 assert (Ex && "Block must have a terminator.");
435
436 // Get the predecessor node and check if is a PostStmt with the Stmt
437 // being the terminator condition. We want to inspect the state
438 // of that node instead because it will contain main information about
439 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000440 assert (!(*I)->pred_empty());
441
442 // Note: any predecessor will do. They should have identical state,
443 // since all the BlockEdge did was act as an error sink since the value
444 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000445 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000446 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000447 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000448
449 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
450 if (PS->getStmt() == Ex)
451 St = N->getState();
452
453 FindUndefExpr FindIt(Eng.getStateManager(), St);
454 Ex = FindIt.FindExpr(Ex);
455
Ted Kremenek85ac9342009-05-15 05:25:09 +0000456 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000457 R->addRange(Ex->getSourceRange());
458 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000459 }
460 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000461
462 void registerInitialVisitors(BugReporterContext& BRC,
463 const ExplodedNode<GRState>* N,
464 BuiltinBugReport *R) {
465 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
466 N);
467 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000468};
469
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000470class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
471public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000472 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000473 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000474 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000475
Ted Kremenekcf118d42009-02-04 23:49:09 +0000476 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000477 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
478 }
479};
Ted Kremenekefd59942008-12-08 22:47:34 +0000480
Ted Kremenek159d2482008-12-09 00:44:16 +0000481class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000482public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000483 BadSizeVLA(GRExprEngine* eng) :
484 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Ted Kremenekefd59942008-12-08 22:47:34 +0000485
Ted Kremenekcf118d42009-02-04 23:49:09 +0000486 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000487 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000488 I = Eng.ExplicitBadSizedVLA.begin(),
489 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
490
491 // Determine whether this was a 'zero-sized' VLA or a VLA with an
492 // undefined size.
493 GRExprEngine::NodeTy* N = *I;
494 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenekefd59942008-12-08 22:47:34 +0000495 DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
496 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
497 QualType T = Eng.getContext().getCanonicalType(VD->getType());
498 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000499 Expr* SizeExpr = VT->getSizeExpr();
Ted Kremenekefd59942008-12-08 22:47:34 +0000500
Ted Kremenek159d2482008-12-09 00:44:16 +0000501 std::string buf;
502 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000503 os << "The expression used to specify the number of elements in the "
504 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000505 << VD->getNameAsString() << "' evaluates to ";
Ted Kremenek159d2482008-12-09 00:44:16 +0000506
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000507 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Ted Kremenekd49967f2009-04-29 21:58:13 +0000508
509 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000510 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000511 else
512 os << "0. VLAs with no elements have undefined behavior.";
Ted Kremenekd49967f2009-04-29 21:58:13 +0000513
514 std::string shortBuf;
515 llvm::raw_string_ostream os_short(shortBuf);
516 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000517 << (isUndefined ? "garbage value for array size"
518 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000519
Ted Kremenek85ac9342009-05-15 05:25:09 +0000520 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
521 os.str().c_str(), N, SizeExpr);
522
Ted Kremenekcf118d42009-02-04 23:49:09 +0000523 report->addRange(SizeExpr->getSourceRange());
524 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000525 }
526 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000527
528 void registerInitialVisitors(BugReporterContext& BRC,
529 const ExplodedNode<GRState>* N,
530 BuiltinBugReport *R) {
531 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
532 N);
533 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000534};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000535
Ted Kremenek78d46242008-07-22 16:21:24 +0000536//===----------------------------------------------------------------------===//
537// __attribute__(nonnull) checking
538
539class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000540 BugType *BT;
541 BugReporter &BR;
Ted Kremenek78d46242008-07-22 16:21:24 +0000542
543public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000544 CheckAttrNonNull(BugReporter &br) : BT(0), BR(br) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000545
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000546 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000547 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000548 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000549
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000550 SVal X = state->getSVal(CE->getCallee());
Zhongxing Xu369f4472009-04-20 05:24:46 +0000551
552 const FunctionDecl* FD = X.getAsFunctionDecl();
553 if (!FD)
Ted Kremenek78d46242008-07-22 16:21:24 +0000554 return false;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000555
Argyrios Kyrtzidis40b598e2009-06-30 02:34:44 +0000556 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000557
558 if (!Att)
559 return false;
560
561 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000562 unsigned idx = 0;
563 bool hasError = false;
564
565 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
566 ++I, ++idx) {
567
568 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
569 continue;
Ted Kremenekcf118d42009-02-04 23:49:09 +0000570
571 // Lazily allocate the BugType object if it hasn't already been created.
572 // Ownership is transferred to the BugReporter object once the BugReport
573 // is passed to 'EmitWarning'.
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000574 if (!BT) BT =
575 new BugType("Argument with 'nonnull' attribute passed null", "API");
Ted Kremenek78d46242008-07-22 16:21:24 +0000576
Ted Kremenekcf118d42009-02-04 23:49:09 +0000577 RangedBugReport *R = new RangedBugReport(*BT,
578 "Null pointer passed as an argument to a "
579 "'nonnull' parameter", N);
580
581 R->addRange((*I)->getSourceRange());
582 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000583 hasError = true;
584 }
585
586 return hasError;
587 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000588};
589} // end anonymous namespace
590
591//===----------------------------------------------------------------------===//
592// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000593//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000594
595void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000596 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
597 // are different than what probably many checks will do since they don't
598 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
599 // analyzing a function. Generation of BugReport objects is done via a call
600 // to 'FlushReports' from BugReporter.
601 BR.Register(new NullDeref(this));
602 BR.Register(new UndefinedDeref(this));
603 BR.Register(new UndefBranch(this));
604 BR.Register(new DivZero(this));
605 BR.Register(new UndefResult(this));
606 BR.Register(new BadCall(this));
607 BR.Register(new RetStack(this));
608 BR.Register(new RetUndef(this));
609 BR.Register(new BadArg(this));
610 BR.Register(new BadMsgExprArg(this));
611 BR.Register(new BadReceiver(this));
612 BR.Register(new OutOfBoundMemoryAccess(this));
613 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000614 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000615 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000616
617 // The following checks do not need to have their associated BugTypes
618 // explicitly registered with the BugReporter. If they issue any BugReports,
619 // their associated BugType will get registered with the BugReporter
620 // automatically. Note that the check itself is owned by the GRExprEngine
621 // object.
622 AddCheck(new CheckAttrNonNull(BR), Stmt::CallExprClass);
Ted Kremenek78d46242008-07-22 16:21:24 +0000623}