blob: 541282da3e5941e752b59e39af34acab9de0471f [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;
23
24//===----------------------------------------------------------------------===//
25// Utility functions.
26//===----------------------------------------------------------------------===//
27
28template <typename ITERATOR> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000029ExplodedNode<GRState>* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000030 return *I;
31}
32
33template <> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000034ExplodedNode<GRState>* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000035 return I->first;
36}
37
38//===----------------------------------------------------------------------===//
Ted Kremenekdd986cc2009-05-07 00:45:33 +000039// Forward declarations for bug reporter visitors.
40//===----------------------------------------------------------------------===//
41
42static void registerTrackNullValue(BugReporterContext& BRC,
43 const ExplodedNode<GRState>* N);
44
45//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +000046// Bug Descriptions.
47//===----------------------------------------------------------------------===//
48
49namespace {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000050
51class VISIBILITY_HIDDEN BuiltinBugReport : public BugReport {
52public:
53 BuiltinBugReport(BugType& bt, const char* desc,
54 const ExplodedNode<GRState> *n)
55 : BugReport(bt, desc, n) {}
56
57 void registerInitialVisitors(BugReporterContext& BRC,
58 const ExplodedNode<GRState>* N);
59};
60
Ted Kremenekcf118d42009-02-04 23:49:09 +000061class VISIBILITY_HIDDEN BuiltinBug : public BugType {
62 GRExprEngine &Eng;
Ted Kremenek159d2482008-12-09 00:44:16 +000063protected:
Ted Kremenekcf118d42009-02-04 23:49:09 +000064 const std::string desc;
Ted Kremenek78d46242008-07-22 16:21:24 +000065public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000066 BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
67 : BugType(n, "Logic Errors"), Eng(*eng), desc(d) {}
68
69 BuiltinBug(GRExprEngine *eng, const char* n)
70 : BugType(n, "Logic Errors"), Eng(*eng), desc(n) {}
Ted Kremenek22bda882008-07-31 20:31:27 +000071
Ted Kremenekcf118d42009-02-04 23:49:09 +000072 virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) = 0;
73
74 void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
Ted Kremenek78d46242008-07-22 16:21:24 +000075
Ted Kremenekdd986cc2009-05-07 00:45:33 +000076 virtual void registerInitialVisitors(BugReporterContext& BRC,
77 const ExplodedNode<GRState>* N,
78 BuiltinBugReport *R) {}
79
80 template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
Ted Kremenek78d46242008-07-22 16:21:24 +000081};
82
Ted Kremenekdd986cc2009-05-07 00:45:33 +000083
84template <typename ITER>
85void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
86 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
87 GetNode(I)));
88}
89
90void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
91 const ExplodedNode<GRState>* N) {
92 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
93}
94
Ted Kremenek78d46242008-07-22 16:21:24 +000095class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
96public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000097 NullDeref(GRExprEngine* eng)
Ted Kremenek0fa96542009-04-07 04:54:31 +000098 : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
Ted Kremenek78d46242008-07-22 16:21:24 +000099
Ted Kremenekcf118d42009-02-04 23:49:09 +0000100 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000101 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
102 }
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000103
104 void registerInitialVisitors(BugReporterContext& BRC,
105 const ExplodedNode<GRState>* N,
106 BuiltinBugReport *R) {
107 registerTrackNullValue(BRC, N);
108 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000109};
110
Ted Kremenek21fe8372009-02-19 04:06:22 +0000111class VISIBILITY_HIDDEN NilReceiverStructRet : public BugType {
112 GRExprEngine &Eng;
113public:
114 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000115 BugType("'nil' receiver with struct return type", "Logic Errors"),
Ted Kremenek21fe8372009-02-19 04:06:22 +0000116 Eng(*eng) {}
117
118 void FlushReports(BugReporter& BR) {
119 for (GRExprEngine::nil_receiver_struct_ret_iterator
120 I=Eng.nil_receiver_struct_ret_begin(),
121 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
122
123 std::string sbuf;
124 llvm::raw_string_ostream os(sbuf);
125 PostStmt P = cast<PostStmt>((*I)->getLocation());
126 ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
127 os << "The receiver in the message expression is 'nil' and results in the"
128 " returned value (of type '"
129 << ME->getType().getAsString()
130 << "') to be garbage or otherwise undefined.";
131
132 RangedBugReport *R = new RangedBugReport(*this, os.str().c_str(), *I);
133 R->addRange(ME->getReceiver()->getSourceRange());
134 BR.EmitReport(R);
135 }
136 }
137};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000138
139class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BugType {
140 GRExprEngine &Eng;
141public:
142 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
143 BugType("'nil' receiver with return type larger than sizeof(void *)",
144 "Logic Errors"),
145 Eng(*eng) {}
146
147 void FlushReports(BugReporter& BR) {
148 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
163 RangedBugReport *R = new RangedBugReport(*this, os.str().c_str(), *I);
164 R->addRange(ME->getReceiver()->getSourceRange());
165 BR.EmitReport(R);
166 }
167 }
168};
Ted Kremenek21fe8372009-02-19 04:06:22 +0000169
Ted Kremenek78d46242008-07-22 16:21:24 +0000170class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
171public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000172 UndefinedDeref(GRExprEngine* eng)
Ted Kremenek17a8e072009-03-01 05:43:22 +0000173 : BuiltinBug(eng,"Dereference of undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000174
Ted Kremenekcf118d42009-02-04 23:49:09 +0000175 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000176 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
177 }
178};
179
180class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
181public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000182 DivZero(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000183 : BuiltinBug(eng,"Division-by-zero",
184 "Division by zero or undefined value.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000185
Ted Kremenekcf118d42009-02-04 23:49:09 +0000186 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000187 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
188 }
189};
190
191class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
192public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000193 UndefResult(GRExprEngine* eng) : BuiltinBug(eng,"Undefined result",
Ted Kremenek78d46242008-07-22 16:21:24 +0000194 "Result of operation is undefined.") {}
195
Ted Kremenekcf118d42009-02-04 23:49:09 +0000196 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000197 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
198 }
199};
200
201class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
202public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000203 BadCall(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000204 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000205 "Called function pointer is a null or undefined pointer value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000206
Ted Kremenekcf118d42009-02-04 23:49:09 +0000207 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000208 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
209 }
210};
211
212class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
213public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000214 BadArg(GRExprEngine* eng) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000215 "Pass-by-value argument in function call is undefined.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000216
Ted Kremenekcf118d42009-02-04 23:49:09 +0000217 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000218 : BuiltinBug(eng,"Uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000219
Ted Kremenekcf118d42009-02-04 23:49:09 +0000220 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000221 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
222 E = Eng.undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000223 // Generate a report for this bug.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000224 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(),
225 I->first);
226 report->addRange(I->second->getSourceRange());
227 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000228 }
229 }
230};
231
232class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
233public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000234 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000235 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Ted Kremenek78d46242008-07-22 16:21:24 +0000236
Ted Kremenekcf118d42009-02-04 23:49:09 +0000237 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000238 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Ted Kremenekcf118d42009-02-04 23:49:09 +0000239 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000240 // Generate a report for this bug.
Ted Kremenek21fe8372009-02-19 04:06:22 +0000241 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(),
242 I->first);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000243 report->addRange(I->second->getSourceRange());
244 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000245 }
246 }
247};
248
249class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
250public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000251 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000252 : BuiltinBug(eng,"Uninitialized receiver",
253 "Receiver in message expression is an uninitialized value") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000254
Ted Kremenekcf118d42009-02-04 23:49:09 +0000255 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000256 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000257 End = Eng.undef_receivers_end(); I!=End; ++I) {
258
259 // Generate a report for this bug.
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000260 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(), *I);
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000261 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000262 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
263 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
264 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000265 report->addRange(E->getSourceRange());
266 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000267 }
268 }
269};
Ted Kremenek5917d782008-11-21 00:27:44 +0000270
Ted Kremenek78d46242008-07-22 16:21:24 +0000271class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
272public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000273 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000274 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000275
Ted Kremenekcf118d42009-02-04 23:49:09 +0000276 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000277 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
278 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000279
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000280 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000281 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
282 Expr* E = cast<ReturnStmt>(S)->getRetValue();
283 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000284
285 // Get the value associated with E.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000286 loc::MemRegionVal V =
287 cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
Ted Kremenek9e240492008-10-04 05:50:14 +0000288 E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000289
290 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000291 std::string buf;
292 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000293 SourceRange R;
Ted Kremenek22bda882008-07-31 20:31:27 +0000294
Ted Kremenek8aed8062008-10-31 00:13:20 +0000295 // Check if the region is a compound literal.
296 if (const CompoundLiteralRegion* CR =
297 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
298
299 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
300 os << "Address of stack memory associated with a compound literal "
301 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000302 << BR.getSourceManager()
303 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000304 << " returned.";
305
306 R = CL->getSourceRange();
307 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000308 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
309 const Expr* ARE = AR->getExpr();
310 SourceLocation L = ARE->getLocStart();
311 R = ARE->getSourceRange();
312
313 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000314 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000315 << " returned.";
316 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000317 else {
318 os << "Address of stack memory associated with local variable '"
319 << V.getRegion()->getString() << "' returned.";
320 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000321
Ted Kremenekcf118d42009-02-04 23:49:09 +0000322 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
323 report->addRange(E->getSourceRange());
324 if (R.isValid()) report->addRange(R);
325 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000326 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000327 }
328};
Ted Kremenek5917d782008-11-21 00:27:44 +0000329
330class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
331public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000332 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Uninitialized return value",
Ted Kremenek5917d782008-11-21 00:27:44 +0000333 "Uninitialized or undefined return value returned to caller.") {}
334
Ted Kremenekcf118d42009-02-04 23:49:09 +0000335 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000336 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
337 }
338};
Ted Kremenek78d46242008-07-22 16:21:24 +0000339
340class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
341 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000342 GRStateManager& VM;
343 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000344
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000345 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000346
Ted Kremenekb7714b22008-07-30 17:49:12 +0000347 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000348 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000349 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000350
Ted Kremenekb7714b22008-07-30 17:49:12 +0000351 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000352 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
353 Expr* E2 = FindExpr(ExI);
354 if (E2) return E2;
355 }
356
357 return Ex;
358 }
359
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000360 bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000361 };
362
363public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000364 UndefBranch(GRExprEngine *eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000365 : BuiltinBug(eng,"Use of uninitialized value",
Ted Kremenek78d46242008-07-22 16:21:24 +0000366 "Branch condition evaluates to an uninitialized value.") {}
367
Ted Kremenekcf118d42009-02-04 23:49:09 +0000368 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000369 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
370 E=Eng.undef_branches_end(); I!=E; ++I) {
371
372 // What's going on here: we want to highlight the subexpression of the
373 // condition that is the most likely source of the "uninitialized
374 // branch condition." We do a recursive walk of the condition's
375 // subexpressions and roughly look for the most nested subexpression
376 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000377 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
378 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
379 assert (Ex && "Block must have a terminator.");
380
381 // Get the predecessor node and check if is a PostStmt with the Stmt
382 // being the terminator condition. We want to inspect the state
383 // of that node instead because it will contain main information about
384 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000385 assert (!(*I)->pred_empty());
386
387 // Note: any predecessor will do. They should have identical state,
388 // since all the BlockEdge did was act as an error sink since the value
389 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000390 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000391 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000392 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000393
394 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
395 if (PS->getStmt() == Ex)
396 St = N->getState();
397
398 FindUndefExpr FindIt(Eng.getStateManager(), St);
399 Ex = FindIt.FindExpr(Ex);
400
Ted Kremenekcf118d42009-02-04 23:49:09 +0000401 RangedBugReport *R = new RangedBugReport(*this, desc.c_str(), *I);
402 R->addRange(Ex->getSourceRange());
403 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000404 }
405 }
406};
407
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000408class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
409public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000410 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000411 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000412 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000413
Ted Kremenekcf118d42009-02-04 23:49:09 +0000414 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000415 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
416 }
417};
Ted Kremenekefd59942008-12-08 22:47:34 +0000418
Ted Kremenek159d2482008-12-09 00:44:16 +0000419class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000420public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000421 BadSizeVLA(GRExprEngine* eng) :
422 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Ted Kremenekefd59942008-12-08 22:47:34 +0000423
Ted Kremenekcf118d42009-02-04 23:49:09 +0000424 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000425 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000426 I = Eng.ExplicitBadSizedVLA.begin(),
427 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
428
429 // Determine whether this was a 'zero-sized' VLA or a VLA with an
430 // undefined size.
431 GRExprEngine::NodeTy* N = *I;
432 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenekefd59942008-12-08 22:47:34 +0000433 DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
434 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
435 QualType T = Eng.getContext().getCanonicalType(VD->getType());
436 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000437 Expr* SizeExpr = VT->getSizeExpr();
Ted Kremenekefd59942008-12-08 22:47:34 +0000438
Ted Kremenek159d2482008-12-09 00:44:16 +0000439 std::string buf;
440 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000441 os << "The expression used to specify the number of elements in the "
442 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000443 << VD->getNameAsString() << "' evaluates to ";
Ted Kremenek159d2482008-12-09 00:44:16 +0000444
Ted Kremenekd49967f2009-04-29 21:58:13 +0000445 bool isUndefined = Eng.getStateManager().GetSVal(N->getState(),
446 SizeExpr).isUndef();
447
448 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000449 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000450 else
451 os << "0. VLAs with no elements have undefined behavior.";
Ted Kremenekd49967f2009-04-29 21:58:13 +0000452
453 std::string shortBuf;
454 llvm::raw_string_ostream os_short(shortBuf);
455 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
456 << (isUndefined ? " garbage value for array size"
457 : " has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000458
Ted Kremenekd49967f2009-04-29 21:58:13 +0000459 RangedBugReport *report = new RangedBugReport(*this,
460 os_short.str().c_str(),
461 os.str().c_str(), N);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000462 report->addRange(SizeExpr->getSourceRange());
463 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000464 }
465 }
466};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000467
Ted Kremenek78d46242008-07-22 16:21:24 +0000468//===----------------------------------------------------------------------===//
469// __attribute__(nonnull) checking
470
471class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000472 BugType *BT;
473 BugReporter &BR;
Ted Kremenek78d46242008-07-22 16:21:24 +0000474
475public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000476 CheckAttrNonNull(BugReporter &br) : BT(0), BR(br) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000477
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000478 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000479 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000480 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000481
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000482 SVal X = VMgr.GetSVal(state, CE->getCallee());
Zhongxing Xu369f4472009-04-20 05:24:46 +0000483
484 const FunctionDecl* FD = X.getAsFunctionDecl();
485 if (!FD)
Ted Kremenek78d46242008-07-22 16:21:24 +0000486 return false;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000487
Ted Kremenek78d46242008-07-22 16:21:24 +0000488 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
489
490 if (!Att)
491 return false;
492
493 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000494 unsigned idx = 0;
495 bool hasError = false;
496
497 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
498 ++I, ++idx) {
499
500 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
501 continue;
Ted Kremenekcf118d42009-02-04 23:49:09 +0000502
503 // Lazily allocate the BugType object if it hasn't already been created.
504 // Ownership is transferred to the BugReporter object once the BugReport
505 // is passed to 'EmitWarning'.
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000506 if (!BT) BT =
507 new BugType("Argument with 'nonnull' attribute passed null", "API");
Ted Kremenek78d46242008-07-22 16:21:24 +0000508
Ted Kremenekcf118d42009-02-04 23:49:09 +0000509 RangedBugReport *R = new RangedBugReport(*BT,
510 "Null pointer passed as an argument to a "
511 "'nonnull' parameter", N);
512
513 R->addRange((*I)->getSourceRange());
514 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000515 hasError = true;
516 }
517
518 return hasError;
519 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000520};
521} // end anonymous namespace
522
523//===----------------------------------------------------------------------===//
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000524// Definitions for bug reporter visitors.
525//===----------------------------------------------------------------------===//
526
527namespace {
528class VISIBILITY_HIDDEN TrackConstraintBRVisitor : public BugReporterVisitor {
529 SVal Constraint;
530 const bool Assumption;
531 bool isSatisfied;
532public:
533 TrackConstraintBRVisitor(SVal constraint, bool assumption)
534 : Constraint(constraint), Assumption(assumption), isSatisfied(false) {}
535
536 PathDiagnosticPiece* VisitNode(const ExplodedNode<GRState>* N,
537 const ExplodedNode<GRState>* PrevN,
538 BugReporterContext& BRC) {
539 if (isSatisfied)
540 return NULL;
541
542 // Check if in the previous state it was feasible for this constraint
543 // to *not* be true.
544
545 GRStateManager &StateMgr = BRC.getStateManager();
546 bool isFeasible = false;
547 if (StateMgr.Assume(PrevN->getState(), Constraint, !Assumption,
548 isFeasible)) {
549 assert(isFeasible); // Eventually we don't need 'isFeasible'.
550
551 isSatisfied = true;
552
553 // As a sanity check, make sure that the negation of the constraint
554 // was infeasible in the current state. If it is feasible, we somehow
555 // missed the transition point.
556 isFeasible = false;
557 if (StateMgr.Assume(N->getState(), Constraint, !Assumption,
558 isFeasible)) {
559 assert(isFeasible);
560 return NULL;
561 }
562
563 // We found the transition point for the constraint. We now need to
564 // pretty-print the constraint. (work-in-progress)
565 std::string sbuf;
566 llvm::raw_string_ostream os(sbuf);
567
568 if (isa<Loc>(Constraint)) {
569 os << "Assuming pointer value is ";
570 os << (Assumption ? "non-NULL" : "NULL");
571 }
572
573 if (os.str().empty())
574 return NULL;
575
576 // FIXME: Refactor this into BugReporterContext.
577 Stmt *S = 0;
578 ProgramPoint P = N->getLocation();
579
580 if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
581 CFGBlock *BSrc = BE->getSrc();
582 S = BSrc->getTerminatorCondition();
583 }
584 else if (PostStmt *PS = dyn_cast<PostStmt>(&P)) {
585 S = PS->getStmt();
586 }
587
588 if (!S)
589 return NULL;
590
591 // Construct a new PathDiagnosticPiece.
592 PathDiagnosticLocation L(S, BRC.getSourceManager());
593 return new PathDiagnosticEventPiece(L, os.str());
594 }
595
596 return NULL;
597 }
598};
599} // end anonymous namespace
600
601static void registerTrackConstraint(BugReporterContext& BRC, SVal Constraint,
602 bool Assumption) {
603 BRC.addVisitor(new TrackConstraintBRVisitor(Constraint, Assumption));
604}
605
606static void registerTrackNullValue(BugReporterContext& BRC,
607 const ExplodedNode<GRState>* N) {
608
609 ProgramPoint P = N->getLocation();
610 PostStmt *PS = dyn_cast<PostStmt>(&P);
611
612 if (!PS)
613 return;
614
615 Stmt *S = PS->getStmt();
616
617 if (ArraySubscriptExpr *AE = dyn_cast<ArraySubscriptExpr>(S)) {
618 S = AE->getBase();
619 }
620
621 SVal V = BRC.getStateManager().GetSValAsScalarOrLoc(N->getState(), S);
622
623 // Uncomment this to find cases where we aren't properly getting the
624 // base value that was dereferenced.
625 // assert(!V.isUnknownOrUndef());
626
627 // For now just track when a symbolic value became null.
628 if (loc::MemRegionVal *L = dyn_cast<loc::MemRegionVal>(&V)) {
629 const SubRegion *R = cast<SubRegion>(L->getRegion());
630 while (R && !isa<SymbolicRegion>(R)) {
631 R = dyn_cast<SubRegion>(R->getSuperRegion());
632 }
633
634 if (R) {
635 assert(isa<SymbolicRegion>(R));
636 registerTrackConstraint(BRC, loc::MemRegionVal(R), false);
637 }
638 }
639}
640
641//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000642// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000643//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000644
645void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000646 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
647 // are different than what probably many checks will do since they don't
648 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
649 // analyzing a function. Generation of BugReport objects is done via a call
650 // to 'FlushReports' from BugReporter.
651 BR.Register(new NullDeref(this));
652 BR.Register(new UndefinedDeref(this));
653 BR.Register(new UndefBranch(this));
654 BR.Register(new DivZero(this));
655 BR.Register(new UndefResult(this));
656 BR.Register(new BadCall(this));
657 BR.Register(new RetStack(this));
658 BR.Register(new RetUndef(this));
659 BR.Register(new BadArg(this));
660 BR.Register(new BadMsgExprArg(this));
661 BR.Register(new BadReceiver(this));
662 BR.Register(new OutOfBoundMemoryAccess(this));
663 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000664 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000665 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000666
667 // The following checks do not need to have their associated BugTypes
668 // explicitly registered with the BugReporter. If they issue any BugReports,
669 // their associated BugType will get registered with the BugReporter
670 // automatically. Note that the check itself is owned by the GRExprEngine
671 // object.
672 AddCheck(new CheckAttrNonNull(BR), Stmt::CallExprClass);
Ted Kremenek78d46242008-07-22 16:21:24 +0000673}