blob: c84b6c001b1ea0d1eed2dc5c3eae3c4c4b1a68a9 [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 Kremenekc26a8b02009-07-22 21:46:56 +000017#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000018#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000019#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000020#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000021#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000022
23using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000024using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000025
26//===----------------------------------------------------------------------===//
27// Utility functions.
28//===----------------------------------------------------------------------===//
29
30template <typename ITERATOR> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000031ExplodedNode<GRState>* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000032 return *I;
33}
34
35template <> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000036ExplodedNode<GRState>* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000037 return I->first;
38}
39
40//===----------------------------------------------------------------------===//
41// Bug Descriptions.
42//===----------------------------------------------------------------------===//
43
44namespace {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000045
Ted Kremenek0c313172009-05-13 19:16:35 +000046class VISIBILITY_HIDDEN BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000047public:
48 BuiltinBugReport(BugType& bt, const char* desc,
Ted Kremenek0c313172009-05-13 19:16:35 +000049 ExplodedNode<GRState> *n)
50 : RangedBugReport(bt, desc, n) {}
Ted Kremenekdd986cc2009-05-07 00:45:33 +000051
Ted Kremenek85ac9342009-05-15 05:25:09 +000052 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
53 ExplodedNode<GRState> *n)
54 : RangedBugReport(bt, shortDesc, desc, n) {}
55
Ted Kremenekdd986cc2009-05-07 00:45:33 +000056 void registerInitialVisitors(BugReporterContext& BRC,
57 const ExplodedNode<GRState>* N);
58};
59
Ted Kremenekcf118d42009-02-04 23:49:09 +000060class VISIBILITY_HIDDEN BuiltinBug : public BugType {
61 GRExprEngine &Eng;
Ted Kremenek159d2482008-12-09 00:44:16 +000062protected:
Ted Kremenekcf118d42009-02-04 23:49:09 +000063 const std::string desc;
Ted Kremenek78d46242008-07-22 16:21:24 +000064public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000065 BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
Ted Kremenek0c313172009-05-13 19:16:35 +000066 : BugType(n, "Logic errors"), Eng(*eng), desc(d) {}
Ted Kremenekcf118d42009-02-04 23:49:09 +000067
68 BuiltinBug(GRExprEngine *eng, const char* n)
Ted Kremenek0c313172009-05-13 19:16:35 +000069 : BugType(n, "Logic errors"), Eng(*eng), desc(n) {}
Ted Kremenek22bda882008-07-31 20:31:27 +000070
Ted Kremenekcf118d42009-02-04 23:49:09 +000071 virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) = 0;
72
73 void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
Ted Kremenek78d46242008-07-22 16:21:24 +000074
Ted Kremenekdd986cc2009-05-07 00:45:33 +000075 virtual void registerInitialVisitors(BugReporterContext& BRC,
76 const ExplodedNode<GRState>* N,
77 BuiltinBugReport *R) {}
78
79 template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
Ted Kremenek78d46242008-07-22 16:21:24 +000080};
81
Ted Kremenekdd986cc2009-05-07 00:45:33 +000082
83template <typename ITER>
84void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
85 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
86 GetNode(I)));
87}
88
89void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
90 const ExplodedNode<GRState>* N) {
91 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
92}
93
Ted Kremenek78d46242008-07-22 16:21:24 +000094class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
95public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000096 NullDeref(GRExprEngine* eng)
Ted Kremenek0fa96542009-04-07 04:54:31 +000097 : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
Ted Kremenek78d46242008-07-22 16:21:24 +000098
Ted Kremenekcf118d42009-02-04 23:49:09 +000099 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000100 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
101 }
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000102
103 void registerInitialVisitors(BugReporterContext& BRC,
104 const ExplodedNode<GRState>* N,
105 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000106 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000107 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000108};
109
Ted Kremenek0c313172009-05-13 19:16:35 +0000110class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +0000111public:
112 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000113 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +0000114
Ted Kremenek0c313172009-05-13 19:16:35 +0000115 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +0000116 for (GRExprEngine::nil_receiver_struct_ret_iterator
117 I=Eng.nil_receiver_struct_ret_begin(),
118 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
119
120 std::string sbuf;
121 llvm::raw_string_ostream os(sbuf);
122 PostStmt P = cast<PostStmt>((*I)->getLocation());
123 ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
124 os << "The receiver in the message expression is 'nil' and results in the"
125 " returned value (of type '"
126 << ME->getType().getAsString()
127 << "') to be garbage or otherwise undefined.";
128
Ted Kremenek0c313172009-05-13 19:16:35 +0000129 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +0000130 R->addRange(ME->getReceiver()->getSourceRange());
131 BR.EmitReport(R);
132 }
133 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000134
135 void registerInitialVisitors(BugReporterContext& BRC,
136 const ExplodedNode<GRState>* N,
137 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000138 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000139 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000140};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000141
Ted Kremenek0c313172009-05-13 19:16:35 +0000142class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000143public:
144 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000145 BuiltinBug(eng,
146 "'nil' receiver with return type larger than sizeof(void *)") {}
Ted Kremenek899b3de2009-04-08 03:07:17 +0000147
Ted Kremenek0c313172009-05-13 19:16:35 +0000148 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000149 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
150 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
151 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
152
153 std::string sbuf;
154 llvm::raw_string_ostream os(sbuf);
155 PostStmt P = cast<PostStmt>((*I)->getLocation());
156 ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
157 os << "The receiver in the message expression is 'nil' and results in the"
158 " returned value (of type '"
159 << ME->getType().getAsString()
160 << "' and of size "
161 << Eng.getContext().getTypeSize(ME->getType()) / 8
162 << " bytes) to be garbage or otherwise undefined.";
163
Ted Kremenek0c313172009-05-13 19:16:35 +0000164 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000165 R->addRange(ME->getReceiver()->getSourceRange());
166 BR.EmitReport(R);
167 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000168 }
169 void registerInitialVisitors(BugReporterContext& BRC,
170 const ExplodedNode<GRState>* N,
171 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000172 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000173 }
174};
Ted Kremenek21fe8372009-02-19 04:06:22 +0000175
Ted Kremenek78d46242008-07-22 16:21:24 +0000176class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
177public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000178 UndefinedDeref(GRExprEngine* eng)
Ted Kremenek17a8e072009-03-01 05:43:22 +0000179 : BuiltinBug(eng,"Dereference of undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000180
Ted Kremenekcf118d42009-02-04 23:49:09 +0000181 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000182 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
183 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000184
185 void registerInitialVisitors(BugReporterContext& BRC,
186 const ExplodedNode<GRState>* N,
187 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000188 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000189 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000190};
191
192class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
193public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000194 DivZero(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000195 : BuiltinBug(eng,"Division-by-zero",
196 "Division by zero or undefined value.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000197
Ted Kremenekcf118d42009-02-04 23:49:09 +0000198 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000199 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
200 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000201
202 void registerInitialVisitors(BugReporterContext& BRC,
203 const ExplodedNode<GRState>* N,
204 BuiltinBugReport *R) {
205 registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
206 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000207};
208
209class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
210public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000211 UndefResult(GRExprEngine* eng) : BuiltinBug(eng,"Undefined result",
Ted Kremenek78d46242008-07-22 16:21:24 +0000212 "Result of operation is undefined.") {}
213
Ted Kremenekcf118d42009-02-04 23:49:09 +0000214 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000215 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
216 }
217};
218
219class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
220public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000221 BadCall(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000222 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000223 "Called function pointer is a null or undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000224
Ted Kremenekcf118d42009-02-04 23:49:09 +0000225 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000226 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
227 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000228
229 void registerInitialVisitors(BugReporterContext& BRC,
230 const ExplodedNode<GRState>* N,
231 BuiltinBugReport *R) {
232 registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
233 }
234};
235
236
237class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
238 const Stmt *Arg;
239public:
240 ArgReport(BugType& bt, const char* desc, ExplodedNode<GRState> *n,
241 const Stmt *arg)
242 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
243
244 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
245 ExplodedNode<GRState> *n, const Stmt *arg)
246 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
247
248 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000249};
250
251class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000252public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000253 BadArg(GRExprEngine* eng) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000254 "Pass-by-value argument in function call is undefined.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000255
Ted Kremenekcf118d42009-02-04 23:49:09 +0000256 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000257 : BuiltinBug(eng,"Uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000258
Ted Kremenekcf118d42009-02-04 23:49:09 +0000259 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000260 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
261 E = Eng.undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000262 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000263 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
264 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000265 report->addRange(I->second->getSourceRange());
266 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000267 }
268 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000269
270 void registerInitialVisitors(BugReporterContext& BRC,
271 const ExplodedNode<GRState>* N,
272 BuiltinBugReport *R) {
273 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
274 N);
275 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000276};
277
278class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
279public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000280 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000281 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Ted Kremenek78d46242008-07-22 16:21:24 +0000282
Ted Kremenekcf118d42009-02-04 23:49:09 +0000283 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000284 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Ted Kremenekcf118d42009-02-04 23:49:09 +0000285 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000286 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000287 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
288 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000289 report->addRange(I->second->getSourceRange());
290 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000291 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000292 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000293};
294
295class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
296public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000297 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000298 : BuiltinBug(eng,"Uninitialized receiver",
299 "Receiver in message expression is an uninitialized value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000300
Ted Kremenekcf118d42009-02-04 23:49:09 +0000301 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000302 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000303 End = Eng.undef_receivers_end(); I!=End; ++I) {
304
305 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000306 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000307 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000308 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
309 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
310 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000311 report->addRange(E->getSourceRange());
312 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000313 }
314 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000315
Ted Kremenek0c313172009-05-13 19:16:35 +0000316 void registerInitialVisitors(BugReporterContext& BRC,
317 const ExplodedNode<GRState>* N,
318 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000319 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
320 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000321};
Ted Kremenek5917d782008-11-21 00:27:44 +0000322
Ted Kremenek78d46242008-07-22 16:21:24 +0000323class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
324public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000325 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000326 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000327
Ted Kremenekcf118d42009-02-04 23:49:09 +0000328 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000329 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
330 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000331
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000332 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000333 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
334 Expr* E = cast<ReturnStmt>(S)->getRetValue();
335 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000336
337 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000338 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000339
340 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000341 std::string buf;
342 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000343 SourceRange R;
Ted Kremenek22bda882008-07-31 20:31:27 +0000344
Ted Kremenek8aed8062008-10-31 00:13:20 +0000345 // Check if the region is a compound literal.
346 if (const CompoundLiteralRegion* CR =
347 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
348
349 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
350 os << "Address of stack memory associated with a compound literal "
351 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000352 << BR.getSourceManager()
353 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000354 << " returned.";
355
356 R = CL->getSourceRange();
357 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000358 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
359 const Expr* ARE = AR->getExpr();
360 SourceLocation L = ARE->getLocStart();
361 R = ARE->getSourceRange();
362
363 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000364 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000365 << " returned.";
366 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000367 else {
368 os << "Address of stack memory associated with local variable '"
369 << V.getRegion()->getString() << "' returned.";
370 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000371
Ted Kremenekcf118d42009-02-04 23:49:09 +0000372 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
373 report->addRange(E->getSourceRange());
374 if (R.isValid()) report->addRange(R);
375 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000376 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000377 }
378};
Ted Kremenek5917d782008-11-21 00:27:44 +0000379
380class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
381public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000382 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Uninitialized return value",
Ted Kremenek0c313172009-05-13 19:16:35 +0000383 "Uninitialized or undefined value returned to caller.") {}
Ted Kremenek5917d782008-11-21 00:27:44 +0000384
Ted Kremenekcf118d42009-02-04 23:49:09 +0000385 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000386 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
387 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000388
389 void registerInitialVisitors(BugReporterContext& BRC,
390 const ExplodedNode<GRState>* N,
391 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000392 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
393 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000394};
Ted Kremenek78d46242008-07-22 16:21:24 +0000395
396class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
397 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000398 GRStateManager& VM;
399 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000400
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000401 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000402
Ted Kremenekb7714b22008-07-30 17:49:12 +0000403 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000404 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000405 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000406
Ted Kremenekb7714b22008-07-30 17:49:12 +0000407 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000408 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
409 Expr* E2 = FindExpr(ExI);
410 if (E2) return E2;
411 }
412
413 return Ex;
414 }
415
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000416 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000417 };
418
419public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000420 UndefBranch(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000421 : BuiltinBug(eng,"Use of uninitialized value",
Ted Kremenek78d46242008-07-22 16:21:24 +0000422 "Branch condition evaluates to an uninitialized value.") {}
423
Ted Kremenekcf118d42009-02-04 23:49:09 +0000424 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000425 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
426 E=Eng.undef_branches_end(); I!=E; ++I) {
427
428 // What's going on here: we want to highlight the subexpression of the
429 // condition that is the most likely source of the "uninitialized
430 // branch condition." We do a recursive walk of the condition's
431 // subexpressions and roughly look for the most nested subexpression
432 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000433 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
434 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
435 assert (Ex && "Block must have a terminator.");
436
437 // Get the predecessor node and check if is a PostStmt with the Stmt
438 // being the terminator condition. We want to inspect the state
439 // of that node instead because it will contain main information about
440 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000441 assert (!(*I)->pred_empty());
442
443 // Note: any predecessor will do. They should have identical state,
444 // since all the BlockEdge did was act as an error sink since the value
445 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000446 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000447 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000448 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000449
450 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
451 if (PS->getStmt() == Ex)
452 St = N->getState();
453
454 FindUndefExpr FindIt(Eng.getStateManager(), St);
455 Ex = FindIt.FindExpr(Ex);
456
Ted Kremenek85ac9342009-05-15 05:25:09 +0000457 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000458 R->addRange(Ex->getSourceRange());
459 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000460 }
461 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000462
463 void registerInitialVisitors(BugReporterContext& BRC,
464 const ExplodedNode<GRState>* N,
465 BuiltinBugReport *R) {
466 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
467 N);
468 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000469};
470
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000471class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
472public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000473 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000474 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000475 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000476
Ted Kremenekcf118d42009-02-04 23:49:09 +0000477 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000478 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
479 }
480};
Ted Kremenekefd59942008-12-08 22:47:34 +0000481
Ted Kremenek159d2482008-12-09 00:44:16 +0000482class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000483public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000484 BadSizeVLA(GRExprEngine* eng) :
485 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Ted Kremenekefd59942008-12-08 22:47:34 +0000486
Ted Kremenekcf118d42009-02-04 23:49:09 +0000487 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000488 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000489 I = Eng.ExplicitBadSizedVLA.begin(),
490 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
491
492 // Determine whether this was a 'zero-sized' VLA or a VLA with an
493 // undefined size.
494 GRExprEngine::NodeTy* N = *I;
495 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenekefd59942008-12-08 22:47:34 +0000496 DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
497 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
498 QualType T = Eng.getContext().getCanonicalType(VD->getType());
499 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000500 Expr* SizeExpr = VT->getSizeExpr();
Ted Kremenekefd59942008-12-08 22:47:34 +0000501
Ted Kremenek159d2482008-12-09 00:44:16 +0000502 std::string buf;
503 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000504 os << "The expression used to specify the number of elements in the "
505 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000506 << VD->getNameAsString() << "' evaluates to ";
Ted Kremenek159d2482008-12-09 00:44:16 +0000507
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000508 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Ted Kremenekd49967f2009-04-29 21:58:13 +0000509
510 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000511 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000512 else
513 os << "0. VLAs with no elements have undefined behavior.";
Ted Kremenekd49967f2009-04-29 21:58:13 +0000514
515 std::string shortBuf;
516 llvm::raw_string_ostream os_short(shortBuf);
517 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000518 << (isUndefined ? "garbage value for array size"
519 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000520
Ted Kremenek85ac9342009-05-15 05:25:09 +0000521 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
522 os.str().c_str(), N, SizeExpr);
523
Ted Kremenekcf118d42009-02-04 23:49:09 +0000524 report->addRange(SizeExpr->getSourceRange());
525 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000526 }
527 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000528
529 void registerInitialVisitors(BugReporterContext& BRC,
530 const ExplodedNode<GRState>* N,
531 BuiltinBugReport *R) {
532 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
533 N);
534 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000535};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000536
Ted Kremenek78d46242008-07-22 16:21:24 +0000537//===----------------------------------------------------------------------===//
538// __attribute__(nonnull) checking
539
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000540class VISIBILITY_HIDDEN CheckAttrNonNull :
541 public CheckerVisitor<CheckAttrNonNull> {
542
Ted Kremenekcf118d42009-02-04 23:49:09 +0000543 BugType *BT;
Ted Kremenek78d46242008-07-22 16:21:24 +0000544
545public:
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000546 CheckAttrNonNull() : BT(0) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000547
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000548 const void *getTag() {
549 static int x = 0;
550 return &x;
551 }
552
553 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
554 const GRState *state = C.getState();
555 const GRState *originalState = state;
Ted Kremenek78d46242008-07-22 16:21:24 +0000556
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000557 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000558 SVal X = state->getSVal(CE->getCallee());
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000559
Zhongxing Xu369f4472009-04-20 05:24:46 +0000560 const FunctionDecl* FD = X.getAsFunctionDecl();
561 if (!FD)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000562 return;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000563
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000564 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000565 if (!Att)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000566 return;
Ted Kremenek78d46242008-07-22 16:21:24 +0000567
568 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000569 unsigned idx = 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000570
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000571 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
Ted Kremenek78d46242008-07-22 16:21:24 +0000572 ++I, ++idx) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000573
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000574 if (!Att->isNonNull(idx))
575 continue;
576
577 ConstraintManager &CM = C.getConstraintManager();
578 const GRState *stateNotNull, *stateNull;
579 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state,
580 state->getSVal(*I));
581
582 if (stateNull && !stateNotNull) {
583 // Generate an error node. Check for a null node in case
584 // we cache out.
585 if (ExplodedNode<GRState> *errorNode = C.generateNode(CE, stateNull)) {
586
587 // Lazily allocate the BugType object if it hasn't already been
588 // created. Ownership is transferred to the BugReporter object once
589 // the BugReport is passed to 'EmitWarning'.
590 if (!BT)
591 BT = new BugType("Argument with 'nonnull' attribute passed null",
592 "API");
593
594 RangedBugReport *R =
595 new RangedBugReport(*BT, "Null pointer passed as an argument to a "
596 "'nonnull' parameter", errorNode);
597
598 // Highlight the range of the argument that was null.
599 R->addRange((*I)->getSourceRange());
600
601 // Emit the bug report.
602 C.EmitReport(R);
603 }
604
605 // Always return. Either we cached out or we just emitted an error.
606 return;
607 }
608
609 // If a pointer value passed the check we should assume that it is
610 // indeed not null from this point forward.
611 assert(stateNotNull);
612 state = stateNotNull;
613 }
614
615 // If we reach here all of the arguments passed the nonnull check.
616 // If 'state' has been updated generated a new node.
617 if (state != originalState)
618 C.generateNode(CE, state);
Ted Kremenek78d46242008-07-22 16:21:24 +0000619 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000620};
621} // end anonymous namespace
622
623//===----------------------------------------------------------------------===//
624// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000625//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000626
627void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000628 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
629 // are different than what probably many checks will do since they don't
630 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
631 // analyzing a function. Generation of BugReport objects is done via a call
632 // to 'FlushReports' from BugReporter.
633 BR.Register(new NullDeref(this));
634 BR.Register(new UndefinedDeref(this));
635 BR.Register(new UndefBranch(this));
636 BR.Register(new DivZero(this));
637 BR.Register(new UndefResult(this));
638 BR.Register(new BadCall(this));
639 BR.Register(new RetStack(this));
640 BR.Register(new RetUndef(this));
641 BR.Register(new BadArg(this));
642 BR.Register(new BadMsgExprArg(this));
643 BR.Register(new BadReceiver(this));
644 BR.Register(new OutOfBoundMemoryAccess(this));
645 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000646 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000647 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000648
649 // The following checks do not need to have their associated BugTypes
650 // explicitly registered with the BugReporter. If they issue any BugReports,
651 // their associated BugType will get registered with the BugReporter
652 // automatically. Note that the check itself is owned by the GRExprEngine
653 // object.
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000654 registerCheck(new CheckAttrNonNull());
Ted Kremenek78d46242008-07-22 16:21:24 +0000655}