blob: da24192c9d5a61e72f357ad4a778f7af4c686881 [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
Zhongxing Xuc5619d92009-08-06 01:32:16 +000031ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000032 return *I;
33}
34
35template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000036ExplodedNode* 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,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000049 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000050 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000051
Ted Kremenek85ac9342009-05-15 05:25:09 +000052 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000053 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000054 : RangedBugReport(bt, shortDesc, desc, n) {}
55
Ted Kremenekdd986cc2009-05-07 00:45:33 +000056 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000057 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000058};
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) {}
Zhongxing Xu904e1e32009-09-02 07:09:39 +000070
71 const std::string &getDescription() const { return desc; }
Mike Stump1eb44332009-09-09 15:08:12 +000072
Zhongxing Xud99f3612009-09-02 08:10:35 +000073 virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {}
Ted Kremenekcf118d42009-02-04 23:49:09 +000074
75 void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
Mike Stump1eb44332009-09-09 15:08:12 +000076
Ted Kremenekdd986cc2009-05-07 00:45:33 +000077 virtual void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000078 const ExplodedNode* N,
Ted Kremenekdd986cc2009-05-07 00:45:33 +000079 BuiltinBugReport *R) {}
Mike Stump1eb44332009-09-09 15:08:12 +000080
Ted Kremenekdd986cc2009-05-07 00:45:33 +000081 template <typename ITER> void Emit(BugReporter& BR, ITER I, ITER E);
Ted Kremenek78d46242008-07-22 16:21:24 +000082};
Mike Stump1eb44332009-09-09 15:08:12 +000083
84
Ted Kremenekdd986cc2009-05-07 00:45:33 +000085template <typename ITER>
86void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
87 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
88 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000089}
Ted Kremenekdd986cc2009-05-07 00:45:33 +000090
91void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000092 const ExplodedNode* N) {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000093 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
Mike Stump1eb44332009-09-09 15:08:12 +000094}
95
Ted Kremenek78d46242008-07-22 16:21:24 +000096class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
97public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000098 NullDeref(GRExprEngine* eng)
Ted Kremenek0fa96542009-04-07 04:54:31 +000099 : BuiltinBug(eng,"Null dereference", "Dereference of null pointer") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000100
Ted Kremenekcf118d42009-02-04 23:49:09 +0000101 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000102 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
103 }
Mike Stump1eb44332009-09-09 15:08:12 +0000104
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000105 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000106 const ExplodedNode* N,
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000107 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000108 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenekdd986cc2009-05-07 00:45:33 +0000109 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000110};
Mike Stump1eb44332009-09-09 15:08:12 +0000111
Ted Kremenek0c313172009-05-13 19:16:35 +0000112class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +0000113public:
114 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000115 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +0000116
Ted Kremenek0c313172009-05-13 19:16:35 +0000117 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +0000118 for (GRExprEngine::nil_receiver_struct_ret_iterator
119 I=Eng.nil_receiver_struct_ret_begin(),
120 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
121
122 std::string sbuf;
123 llvm::raw_string_ostream os(sbuf);
124 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000125 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +0000126 os << "The receiver in the message expression is 'nil' and results in the"
127 " returned value (of type '"
128 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000129 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +0000130
Ted Kremenek0c313172009-05-13 19:16:35 +0000131 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +0000132 R->addRange(ME->getReceiver()->getSourceRange());
133 BR.EmitReport(R);
134 }
135 }
Mike Stump1eb44332009-09-09 15:08:12 +0000136
Ted Kremenek0c313172009-05-13 19:16:35 +0000137 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000138 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000139 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000140 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000141 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000142};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000143
Ted Kremenek0c313172009-05-13 19:16:35 +0000144class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000145public:
146 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000147 BuiltinBug(eng,
148 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000149
Ted Kremenek0c313172009-05-13 19:16:35 +0000150 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000151 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
152 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
153 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000154
Ted Kremenek899b3de2009-04-08 03:07:17 +0000155 std::string sbuf;
156 llvm::raw_string_ostream os(sbuf);
157 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000158 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000159 os << "The receiver in the message expression is 'nil' and results in the"
160 " returned value (of type '"
161 << ME->getType().getAsString()
162 << "' and of size "
163 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000164 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000165
Ted Kremenek0c313172009-05-13 19:16:35 +0000166 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000167 R->addRange(ME->getReceiver()->getSourceRange());
168 BR.EmitReport(R);
169 }
Mike Stump1eb44332009-09-09 15:08:12 +0000170 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000171 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000172 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000173 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000174 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000175 }
176};
Mike Stump1eb44332009-09-09 15:08:12 +0000177
Ted Kremenek78d46242008-07-22 16:21:24 +0000178class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
179public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000180 UndefinedDeref(GRExprEngine* eng)
Ted Kremenek17a8e072009-03-01 05:43:22 +0000181 : BuiltinBug(eng,"Dereference of undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000182
Ted Kremenekcf118d42009-02-04 23:49:09 +0000183 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000184 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
185 }
Mike Stump1eb44332009-09-09 15:08:12 +0000186
Ted Kremenek0c313172009-05-13 19:16:35 +0000187 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000188 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000189 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000190 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000191 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000192};
193
194class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
195public:
Zhongxing Xu6403b572009-09-02 13:26:26 +0000196 DivZero(GRExprEngine* eng = 0)
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000197 : BuiltinBug(eng,"Division by zero") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000198
Ted Kremenek85ac9342009-05-15 05:25:09 +0000199 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000200 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000201 BuiltinBugReport *R) {
202 registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
203 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000204};
Mike Stump1eb44332009-09-09 15:08:12 +0000205
Ted Kremenek78d46242008-07-22 16:21:24 +0000206class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
207public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000208 UndefResult(GRExprEngine* eng)
209 : BuiltinBug(eng,"Undefined or garbage result",
210 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000211
Ted Kremenekcf118d42009-02-04 23:49:09 +0000212 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000213 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
214 E = Eng.undef_results_end(); I!=E; ++I) {
215
216 ExplodedNode *N = *I;
217 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
218 BuiltinBugReport *report = NULL;
219
220 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
221 llvm::SmallString<256> sbuf;
222 llvm::raw_svector_ostream OS(sbuf);
223 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000224 const Expr *Ex = NULL;
225 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000226
227 if (ST->getSVal(B->getLHS()).isUndef()) {
228 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000229 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000230 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000231 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000232 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000233 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000234 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000235
236 if (Ex) {
237 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000238 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000239 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000240 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000241 }
242 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000243 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000244 OS << "The result of the '"
245 << BinaryOperator::getOpcodeStr(B->getOpcode())
246 << "' expression is undefined";
247 }
248
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000249 // FIXME: Use StringRefs to pass string information.
250 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000251 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000252 }
253 else {
254 report = new BuiltinBugReport(*this,
255 "Expression evaluates to an uninitialized"
256 " or undefined value", N);
257 }
258
259 BR.EmitReport(report);
260 }
261 }
262
263 void registerInitialVisitors(BugReporterContext& BRC,
264 const ExplodedNode* N,
265 BuiltinBugReport *R) {
266
267 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
268 const Stmt *X = S;
269
270 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
271 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000272 if (ST->getSVal(B->getLHS()).isUndef())
273 X = B->getLHS();
274 else if (ST->getSVal(B->getRHS()).isUndef())
275 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000276 }
277
278 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000279 }
280};
Mike Stump1eb44332009-09-09 15:08:12 +0000281
Ted Kremenek78d46242008-07-22 16:21:24 +0000282class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
283public:
Zhongxing Xud99f3612009-09-02 08:10:35 +0000284 BadCall(GRExprEngine *eng = 0)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000285 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000286 "Called function pointer is a null or undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000287
Ted Kremenek85ac9342009-05-15 05:25:09 +0000288 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000289 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000290 BuiltinBugReport *R) {
291 registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
292 }
293};
294
295
296class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
297 const Stmt *Arg;
298public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000299 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000300 const Stmt *arg)
301 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000302
Ted Kremenek85ac9342009-05-15 05:25:09 +0000303 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000304 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000305 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
306
307 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000308};
309
310class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000311public:
312 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000313 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000314
Ted Kremenekcf118d42009-02-04 23:49:09 +0000315 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000316 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000317
Ted Kremenek85ac9342009-05-15 05:25:09 +0000318 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000319 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000320 BuiltinBugReport *R) {
321 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
322 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000323 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000324};
Mike Stump1eb44332009-09-09 15:08:12 +0000325
Ted Kremenek78d46242008-07-22 16:21:24 +0000326class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
327public:
Mike Stump1eb44332009-09-09 15:08:12 +0000328 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000329 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000330
Ted Kremenekcf118d42009-02-04 23:49:09 +0000331 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000332 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000333 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000334 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000335 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
336 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000337 report->addRange(I->second->getSourceRange());
338 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000339 }
340 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000341};
Mike Stump1eb44332009-09-09 15:08:12 +0000342
Ted Kremenek78d46242008-07-22 16:21:24 +0000343class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000344public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000345 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000346 : BuiltinBug(eng,"Uninitialized receiver",
347 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000348
Ted Kremenekcf118d42009-02-04 23:49:09 +0000349 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000350 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000351 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000352
Ted Kremenek78d46242008-07-22 16:21:24 +0000353 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000354 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000355 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000356 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
357 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000358 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000359 report->addRange(E->getSourceRange());
360 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000361 }
362 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000363
Ted Kremenek0c313172009-05-13 19:16:35 +0000364 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000365 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000366 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000367 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000368 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000369};
Ted Kremenek5917d782008-11-21 00:27:44 +0000370
Ted Kremenek78d46242008-07-22 16:21:24 +0000371class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
372public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000373 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000374 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000375
Ted Kremenekcf118d42009-02-04 23:49:09 +0000376 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000377 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
378 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000379
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000380 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000381 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
382 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
383 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000384
Ted Kremenek22bda882008-07-31 20:31:27 +0000385 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000386 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000387
Ted Kremenek22bda882008-07-31 20:31:27 +0000388 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000389 std::string buf;
390 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000391 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000392
Ted Kremenek8aed8062008-10-31 00:13:20 +0000393 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000394 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000395 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000396
Ted Kremenek8aed8062008-10-31 00:13:20 +0000397 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
398 os << "Address of stack memory associated with a compound literal "
399 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000400 << BR.getSourceManager()
401 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000402 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000403
Ted Kremenek8aed8062008-10-31 00:13:20 +0000404 R = CL->getSourceRange();
405 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000406 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
407 const Expr* ARE = AR->getExpr();
408 SourceLocation L = ARE->getLocStart();
409 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000410
Ted Kremenekde8cd192008-11-02 00:35:25 +0000411 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000412 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000413 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000414 }
415 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000416 os << "Address of stack memory associated with local variable '"
417 << V.getRegion()->getString() << "' returned.";
418 }
Mike Stump1eb44332009-09-09 15:08:12 +0000419
Ted Kremenekcf118d42009-02-04 23:49:09 +0000420 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
421 report->addRange(E->getSourceRange());
422 if (R.isValid()) report->addRange(R);
423 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000424 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000425 }
426};
Mike Stump1eb44332009-09-09 15:08:12 +0000427
Ted Kremenek5917d782008-11-21 00:27:44 +0000428class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
429public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000430 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
431 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000432
Ted Kremenekcf118d42009-02-04 23:49:09 +0000433 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000434 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
435 }
Mike Stump1eb44332009-09-09 15:08:12 +0000436
Ted Kremenek0c313172009-05-13 19:16:35 +0000437 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000438 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000439 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000440 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000441 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000442};
Ted Kremenek78d46242008-07-22 16:21:24 +0000443
444class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
445 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000446 GRStateManager& VM;
447 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000448
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000449 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000450
451 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000452 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000453 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000454
Ted Kremenekb7714b22008-07-30 17:49:12 +0000455 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000456 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
457 Expr* E2 = FindExpr(ExI);
458 if (E2) return E2;
459 }
Mike Stump1eb44332009-09-09 15:08:12 +0000460
Ted Kremenek78d46242008-07-22 16:21:24 +0000461 return Ex;
462 }
Mike Stump1eb44332009-09-09 15:08:12 +0000463
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000464 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000465 };
Mike Stump1eb44332009-09-09 15:08:12 +0000466
Ted Kremenek78d46242008-07-22 16:21:24 +0000467public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000468 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000469 : BuiltinBug(eng,"Use of garbage value",
470 "Branch condition evaluates to an undefined or garbage value")
471 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000472
Ted Kremenekcf118d42009-02-04 23:49:09 +0000473 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000474 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
475 E=Eng.undef_branches_end(); I!=E; ++I) {
476
477 // What's going on here: we want to highlight the subexpression of the
478 // condition that is the most likely source of the "uninitialized
479 // branch condition." We do a recursive walk of the condition's
480 // subexpressions and roughly look for the most nested subexpression
481 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000482 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
483 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
484 assert (Ex && "Block must have a terminator.");
485
486 // Get the predecessor node and check if is a PostStmt with the Stmt
487 // being the terminator condition. We want to inspect the state
488 // of that node instead because it will contain main information about
489 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000490 assert (!(*I)->pred_empty());
491
492 // Note: any predecessor will do. They should have identical state,
493 // since all the BlockEdge did was act as an error sink since the value
494 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000495 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000496 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000497 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000498
499 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
500 if (PS->getStmt() == Ex)
501 St = N->getState();
502
503 FindUndefExpr FindIt(Eng.getStateManager(), St);
504 Ex = FindIt.FindExpr(Ex);
505
Ted Kremenek85ac9342009-05-15 05:25:09 +0000506 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000507 R->addRange(Ex->getSourceRange());
508 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000509 }
510 }
Mike Stump1eb44332009-09-09 15:08:12 +0000511
Ted Kremenek85ac9342009-05-15 05:25:09 +0000512 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000513 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000514 BuiltinBugReport *R) {
515 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
516 N);
517 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000518};
519
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000520class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
521public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000522 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000523 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000524 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000525
Ted Kremenekcf118d42009-02-04 23:49:09 +0000526 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000527 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
528 }
529};
Mike Stump1eb44332009-09-09 15:08:12 +0000530
Ted Kremenek159d2482008-12-09 00:44:16 +0000531class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000532public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000533 BadSizeVLA(GRExprEngine* eng) :
534 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000535
Ted Kremenekcf118d42009-02-04 23:49:09 +0000536 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000537 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000538 I = Eng.ExplicitBadSizedVLA.begin(),
539 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
540
541 // Determine whether this was a 'zero-sized' VLA or a VLA with an
542 // undefined size.
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000543 ExplodedNode* N = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000544 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000545 const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
Ted Kremenekefd59942008-12-08 22:47:34 +0000546 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
547 QualType T = Eng.getContext().getCanonicalType(VD->getType());
548 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000549 Expr* SizeExpr = VT->getSizeExpr();
Mike Stump1eb44332009-09-09 15:08:12 +0000550
Ted Kremenek159d2482008-12-09 00:44:16 +0000551 std::string buf;
552 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000553 os << "The expression used to specify the number of elements in the "
554 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000555 << VD->getNameAsString() << "' evaluates to ";
Mike Stump1eb44332009-09-09 15:08:12 +0000556
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000557 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Mike Stump1eb44332009-09-09 15:08:12 +0000558
Ted Kremenekd49967f2009-04-29 21:58:13 +0000559 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000560 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000561 else
562 os << "0. VLAs with no elements have undefined behavior.";
Mike Stump1eb44332009-09-09 15:08:12 +0000563
Ted Kremenekd49967f2009-04-29 21:58:13 +0000564 std::string shortBuf;
565 llvm::raw_string_ostream os_short(shortBuf);
566 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000567 << (isUndefined ? "garbage value for array size"
568 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000569
Ted Kremenek85ac9342009-05-15 05:25:09 +0000570 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
571 os.str().c_str(), N, SizeExpr);
572
Ted Kremenekcf118d42009-02-04 23:49:09 +0000573 report->addRange(SizeExpr->getSourceRange());
574 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000575 }
576 }
Mike Stump1eb44332009-09-09 15:08:12 +0000577
Ted Kremenek85ac9342009-05-15 05:25:09 +0000578 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000579 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000580 BuiltinBugReport *R) {
581 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
582 N);
583 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000584};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000585
Ted Kremenek78d46242008-07-22 16:21:24 +0000586//===----------------------------------------------------------------------===//
587// __attribute__(nonnull) checking
588
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000589class VISIBILITY_HIDDEN CheckAttrNonNull :
590 public CheckerVisitor<CheckAttrNonNull> {
591
Ted Kremenekcf118d42009-02-04 23:49:09 +0000592 BugType *BT;
Mike Stump1eb44332009-09-09 15:08:12 +0000593
Ted Kremenek78d46242008-07-22 16:21:24 +0000594public:
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000595 CheckAttrNonNull() : BT(0) {}
Ted Kremenek31112182009-07-24 00:40:31 +0000596 ~CheckAttrNonNull() {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000597
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000598 const void *getTag() {
599 static int x = 0;
600 return &x;
601 }
602
603 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
604 const GRState *state = C.getState();
605 const GRState *originalState = state;
Mike Stump1eb44332009-09-09 15:08:12 +0000606
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000607 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000608 SVal X = state->getSVal(CE->getCallee());
Mike Stump1eb44332009-09-09 15:08:12 +0000609
Zhongxing Xu369f4472009-04-20 05:24:46 +0000610 const FunctionDecl* FD = X.getAsFunctionDecl();
611 if (!FD)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000612 return;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000613
Mike Stump1eb44332009-09-09 15:08:12 +0000614 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000615 if (!Att)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000616 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000617
Ted Kremenek78d46242008-07-22 16:21:24 +0000618 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000619 unsigned idx = 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000620
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000621 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
Ted Kremenek78d46242008-07-22 16:21:24 +0000622 ++I, ++idx) {
Mike Stump1eb44332009-09-09 15:08:12 +0000623
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000624 if (!Att->isNonNull(idx))
625 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000626
Ted Kremenek08780072009-08-24 22:47:34 +0000627 const SVal &V = state->getSVal(*I);
628 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
Mike Stump1eb44332009-09-09 15:08:12 +0000629
Ted Kremenek08780072009-08-24 22:47:34 +0000630 if (!DV)
631 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000632
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000633 ConstraintManager &CM = C.getConstraintManager();
634 const GRState *stateNotNull, *stateNull;
Ted Kremenek08780072009-08-24 22:47:34 +0000635 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000636
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000637 if (stateNull && !stateNotNull) {
638 // Generate an error node. Check for a null node in case
639 // we cache out.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000640 if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000641
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000642 // Lazily allocate the BugType object if it hasn't already been
643 // created. Ownership is transferred to the BugReporter object once
644 // the BugReport is passed to 'EmitWarning'.
645 if (!BT)
646 BT = new BugType("Argument with 'nonnull' attribute passed null",
647 "API");
Mike Stump1eb44332009-09-09 15:08:12 +0000648
Ted Kremenek592362b2009-08-18 01:05:30 +0000649 EnhancedBugReport *R =
650 new EnhancedBugReport(*BT,
651 "Null pointer passed as an argument to a "
652 "'nonnull' parameter", errorNode);
Mike Stump1eb44332009-09-09 15:08:12 +0000653
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000654 // Highlight the range of the argument that was null.
Ted Kremenek592362b2009-08-18 01:05:30 +0000655 const Expr *arg = *I;
656 R->addRange(arg->getSourceRange());
657 R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
Mike Stump1eb44332009-09-09 15:08:12 +0000658
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000659 // Emit the bug report.
660 C.EmitReport(R);
661 }
Mike Stump1eb44332009-09-09 15:08:12 +0000662
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000663 // Always return. Either we cached out or we just emitted an error.
664 return;
665 }
Mike Stump1eb44332009-09-09 15:08:12 +0000666
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000667 // If a pointer value passed the check we should assume that it is
668 // indeed not null from this point forward.
669 assert(stateNotNull);
670 state = stateNotNull;
671 }
Mike Stump1eb44332009-09-09 15:08:12 +0000672
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000673 // If we reach here all of the arguments passed the nonnull check.
674 // If 'state' has been updated generated a new node.
675 if (state != originalState)
Zhongxing Xu6403b572009-09-02 13:26:26 +0000676 C.addTransition(C.GenerateNode(CE, state));
Ted Kremenek78d46242008-07-22 16:21:24 +0000677 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000678};
679} // end anonymous namespace
680
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000681// Undefined arguments checking.
682namespace {
Mike Stump1eb44332009-09-09 15:08:12 +0000683class VISIBILITY_HIDDEN CheckUndefinedArg
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000684 : public CheckerVisitor<CheckUndefinedArg> {
685
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000686 BadArg *BT;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000687
688public:
689 CheckUndefinedArg() : BT(0) {}
690 ~CheckUndefinedArg() {}
691
692 const void *getTag() {
693 static int x = 0;
694 return &x;
695 }
696
697 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
698};
699
700void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
701 for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
702 I != E; ++I) {
703 if (C.getState()->getSVal(*I).isUndef()) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000704 if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000705 if (!BT)
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000706 BT = new BadArg();
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000707 // Generate a report for this bug.
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000708 ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000709 ErrorNode, *I);
710 Report->addRange((*I)->getSourceRange());
711 C.EmitReport(Report);
712 }
713 }
714 }
715}
716
Zhongxing Xud99f3612009-09-02 08:10:35 +0000717class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
718 BadCall *BT;
719
720public:
721 CheckBadCall() : BT(0) {}
722 ~CheckBadCall() {}
723
724 const void *getTag() {
725 static int x = 0;
726 return &x;
727 }
728
729 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
730};
731
732void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
733 const Expr *Callee = CE->getCallee()->IgnoreParens();
734 SVal L = C.getState()->getSVal(Callee);
735
736 if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000737 if (ExplodedNode *N = C.GenerateNode(CE, true)) {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000738 if (!BT)
739 BT = new BadCall();
740 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
741 }
742 }
743}
744
Zhongxing Xu524e4652009-10-22 01:58:10 +0000745class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000746 DivZero *BT;
747public:
Zhongxing Xu524e4652009-10-22 01:58:10 +0000748 CheckDivZero() : BT(0) {}
749 ~CheckDivZero() {}
Zhongxing Xu6403b572009-09-02 13:26:26 +0000750
751 const void *getTag() {
752 static int x;
753 return &x;
754 }
755
756 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
757};
758
Zhongxing Xu524e4652009-10-22 01:58:10 +0000759void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
760 const BinaryOperator *B) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000761 BinaryOperator::Opcode Op = B->getOpcode();
762 if (Op != BinaryOperator::Div &&
763 Op != BinaryOperator::Rem &&
764 Op != BinaryOperator::DivAssign &&
765 Op != BinaryOperator::RemAssign)
766 return;
767
768 if (!B->getRHS()->getType()->isIntegerType() ||
769 !B->getRHS()->getType()->isScalarType())
770 return;
771
Zhongxing Xu6403b572009-09-02 13:26:26 +0000772 SVal Denom = C.getState()->getSVal(B->getRHS());
Ted Kremenek970e03a2009-09-03 01:48:03 +0000773 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
774
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000775 // Divide-by-undefined handled in the generic checking for uses of
776 // undefined values.
Mike Stump1eb44332009-09-09 15:08:12 +0000777 if (!DV)
Ted Kremenek970e03a2009-09-03 01:48:03 +0000778 return;
779
Zhongxing Xu6403b572009-09-02 13:26:26 +0000780 // Check for divide by zero.
781 ConstraintManager &CM = C.getConstraintManager();
782 const GRState *stateNotZero, *stateZero;
Ted Kremenek970e03a2009-09-03 01:48:03 +0000783 llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000784
Zhongxing Xu6403b572009-09-02 13:26:26 +0000785 if (stateZero && !stateNotZero) {
786 if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
787 if (!BT)
788 BT = new DivZero();
Mike Stump1eb44332009-09-09 15:08:12 +0000789
Zhongxing Xu6403b572009-09-02 13:26:26 +0000790 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
791 }
792 return;
793 }
794
Zhongxing Xu524e4652009-10-22 01:58:10 +0000795 // If we get here, then the denom should not be zero. We abandon the implicit
796 // zero denom case for now.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000797 if (stateNotZero != C.getState())
798 C.addTransition(C.GenerateNode(B, stateNotZero));
799}
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000800}
Ted Kremenek78d46242008-07-22 16:21:24 +0000801//===----------------------------------------------------------------------===//
802// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000803//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000804
805void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000806 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
807 // are different than what probably many checks will do since they don't
808 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
809 // analyzing a function. Generation of BugReport objects is done via a call
810 // to 'FlushReports' from BugReporter.
811 BR.Register(new NullDeref(this));
812 BR.Register(new UndefinedDeref(this));
813 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000814 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000815 BR.Register(new RetStack(this));
816 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000817 BR.Register(new BadMsgExprArg(this));
818 BR.Register(new BadReceiver(this));
819 BR.Register(new OutOfBoundMemoryAccess(this));
820 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000821 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000822 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000823
Ted Kremenekcf118d42009-02-04 23:49:09 +0000824 // The following checks do not need to have their associated BugTypes
825 // explicitly registered with the BugReporter. If they issue any BugReports,
826 // their associated BugType will get registered with the BugReporter
827 // automatically. Note that the check itself is owned by the GRExprEngine
828 // object.
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000829 registerCheck(new CheckAttrNonNull());
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000830 registerCheck(new CheckUndefinedArg());
Zhongxing Xud99f3612009-09-02 08:10:35 +0000831 registerCheck(new CheckBadCall());
Zhongxing Xu524e4652009-10-22 01:58:10 +0000832 registerCheck(new CheckDivZero());
Ted Kremenek78d46242008-07-22 16:21:24 +0000833}