blob: 526bc93e853272053eb47303ae9853045906db7a [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"
Zhongxing Xuec9227f2009-10-29 02:09:30 +000018#include "clang/Analysis/PathSensitive/NullDerefChecker.h"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000020#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000021#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000022#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000023
24using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000025using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000026
27//===----------------------------------------------------------------------===//
28// Utility functions.
29//===----------------------------------------------------------------------===//
30
31template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000032ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000033 return *I;
34}
35
36template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000037ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000038 return I->first;
39}
40
41//===----------------------------------------------------------------------===//
42// Bug Descriptions.
43//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000044namespace clang {
45class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000046public:
47 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000048 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000049 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000050
Ted Kremenek85ac9342009-05-15 05:25:09 +000051 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000052 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000053 : RangedBugReport(bt, shortDesc, desc, n) {}
54
Ted Kremenekdd986cc2009-05-07 00:45:33 +000055 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000056 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000057};
58
Zhongxing Xuec9227f2009-10-29 02:09:30 +000059void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
60 const ExplodedNode* N) {
61 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
62}
Mike Stump1eb44332009-09-09 15:08:12 +000063
Ted Kremenekdd986cc2009-05-07 00:45:33 +000064template <typename ITER>
65void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
66 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
67 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000068}
Zhongxing Xuec9227f2009-10-29 02:09:30 +000069void NullDeref::registerInitialVisitors(BugReporterContext& BRC,
70 const ExplodedNode* N,
71 BuiltinBugReport *R) {
72 registerTrackNullOrUndefValue(BRC, bugreporter::GetDerefExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +000073}
74
Ted Kremenek0c313172009-05-13 19:16:35 +000075class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000076public:
77 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000078 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000079
Ted Kremenek0c313172009-05-13 19:16:35 +000080 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000081 for (GRExprEngine::nil_receiver_struct_ret_iterator
82 I=Eng.nil_receiver_struct_ret_begin(),
83 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
84
85 std::string sbuf;
86 llvm::raw_string_ostream os(sbuf);
87 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000088 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000089 os << "The receiver in the message expression is 'nil' and results in the"
90 " returned value (of type '"
91 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000092 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000093
Ted Kremenek0c313172009-05-13 19:16:35 +000094 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000095 R->addRange(ME->getReceiver()->getSourceRange());
96 BR.EmitReport(R);
97 }
98 }
Mike Stump1eb44332009-09-09 15:08:12 +000099
Ted Kremenek0c313172009-05-13 19:16:35 +0000100 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000101 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000102 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000103 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000104 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000105};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000106
Ted Kremenek0c313172009-05-13 19:16:35 +0000107class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000108public:
109 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000110 BuiltinBug(eng,
111 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000112
Ted Kremenek0c313172009-05-13 19:16:35 +0000113 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000114 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
115 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
116 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000117
Ted Kremenek899b3de2009-04-08 03:07:17 +0000118 std::string sbuf;
119 llvm::raw_string_ostream os(sbuf);
120 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000121 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000122 os << "The receiver in the message expression is 'nil' and results in the"
123 " returned value (of type '"
124 << ME->getType().getAsString()
125 << "' and of size "
126 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000127 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000128
Ted Kremenek0c313172009-05-13 19:16:35 +0000129 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000130 R->addRange(ME->getReceiver()->getSourceRange());
131 BR.EmitReport(R);
132 }
Mike Stump1eb44332009-09-09 15:08:12 +0000133 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000134 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000135 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000136 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000137 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000138 }
139};
Mike Stump1eb44332009-09-09 15:08:12 +0000140
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000141
142
Ted Kremenek78d46242008-07-22 16:21:24 +0000143class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
144public:
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000145 UndefinedDeref()
146 : BuiltinBug(0, "Dereference of undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000147
Ted Kremenek0c313172009-05-13 19:16:35 +0000148 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000149 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000150 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000151 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000152 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000153};
154
155class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
156public:
Zhongxing Xu6403b572009-09-02 13:26:26 +0000157 DivZero(GRExprEngine* eng = 0)
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000158 : BuiltinBug(eng,"Division by zero") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000159
Ted Kremenek85ac9342009-05-15 05:25:09 +0000160 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000161 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000162 BuiltinBugReport *R) {
163 registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
164 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000165};
Mike Stump1eb44332009-09-09 15:08:12 +0000166
Ted Kremenek78d46242008-07-22 16:21:24 +0000167class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
168public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000169 UndefResult(GRExprEngine* eng)
170 : BuiltinBug(eng,"Undefined or garbage result",
171 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000172
Ted Kremenekcf118d42009-02-04 23:49:09 +0000173 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000174 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
175 E = Eng.undef_results_end(); I!=E; ++I) {
176
177 ExplodedNode *N = *I;
178 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
179 BuiltinBugReport *report = NULL;
180
181 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
182 llvm::SmallString<256> sbuf;
183 llvm::raw_svector_ostream OS(sbuf);
184 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000185 const Expr *Ex = NULL;
186 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000187
188 if (ST->getSVal(B->getLHS()).isUndef()) {
189 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000190 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000191 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000192 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000193 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000194 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000195 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000196
197 if (Ex) {
198 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000199 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000200 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000201 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000202 }
203 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000204 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000205 OS << "The result of the '"
206 << BinaryOperator::getOpcodeStr(B->getOpcode())
207 << "' expression is undefined";
208 }
209
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000210 // FIXME: Use StringRefs to pass string information.
211 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000212 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000213 }
214 else {
215 report = new BuiltinBugReport(*this,
216 "Expression evaluates to an uninitialized"
217 " or undefined value", N);
218 }
219
220 BR.EmitReport(report);
221 }
222 }
223
224 void registerInitialVisitors(BugReporterContext& BRC,
225 const ExplodedNode* N,
226 BuiltinBugReport *R) {
227
228 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
229 const Stmt *X = S;
230
231 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
232 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000233 if (ST->getSVal(B->getLHS()).isUndef())
234 X = B->getLHS();
235 else if (ST->getSVal(B->getRHS()).isUndef())
236 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000237 }
238
239 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000240 }
241};
Mike Stump1eb44332009-09-09 15:08:12 +0000242
Ted Kremenek78d46242008-07-22 16:21:24 +0000243class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
244public:
Zhongxing Xud99f3612009-09-02 08:10:35 +0000245 BadCall(GRExprEngine *eng = 0)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000246 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000247 "Called function pointer is a null or undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000248
Ted Kremenek85ac9342009-05-15 05:25:09 +0000249 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000250 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000251 BuiltinBugReport *R) {
252 registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
253 }
254};
255
256
257class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
258 const Stmt *Arg;
259public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000260 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000261 const Stmt *arg)
262 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000263
Ted Kremenek85ac9342009-05-15 05:25:09 +0000264 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000265 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000266 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
267
268 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000269};
270
271class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000272public:
273 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000274 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000275
Ted Kremenekcf118d42009-02-04 23:49:09 +0000276 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000277 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000278
Ted Kremenek85ac9342009-05-15 05:25:09 +0000279 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000280 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000281 BuiltinBugReport *R) {
282 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
283 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000284 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000285};
Mike Stump1eb44332009-09-09 15:08:12 +0000286
Ted Kremenek78d46242008-07-22 16:21:24 +0000287class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
288public:
Mike Stump1eb44332009-09-09 15:08:12 +0000289 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000290 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000291
Ted Kremenekcf118d42009-02-04 23:49:09 +0000292 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000293 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000294 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000295 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000296 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
297 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000298 report->addRange(I->second->getSourceRange());
299 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000300 }
301 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000302};
Mike Stump1eb44332009-09-09 15:08:12 +0000303
Ted Kremenek78d46242008-07-22 16:21:24 +0000304class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000305public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000306 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000307 : BuiltinBug(eng,"Uninitialized receiver",
308 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000309
Ted Kremenekcf118d42009-02-04 23:49:09 +0000310 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000311 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000312 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000313
Ted Kremenek78d46242008-07-22 16:21:24 +0000314 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000315 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000316 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000317 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
318 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000319 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000320 report->addRange(E->getSourceRange());
321 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000322 }
323 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000324
Ted Kremenek0c313172009-05-13 19:16:35 +0000325 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000326 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000327 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000328 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000329 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000330};
Ted Kremenek5917d782008-11-21 00:27:44 +0000331
Ted Kremenek78d46242008-07-22 16:21:24 +0000332class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
333public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000334 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000335 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000336
Ted Kremenekcf118d42009-02-04 23:49:09 +0000337 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000338 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
339 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000340
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000341 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000342 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
343 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
344 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000345
Ted Kremenek22bda882008-07-31 20:31:27 +0000346 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000347 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000348
Ted Kremenek22bda882008-07-31 20:31:27 +0000349 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000350 std::string buf;
351 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000352 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000353
Ted Kremenek8aed8062008-10-31 00:13:20 +0000354 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000355 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000356 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000357
Ted Kremenek8aed8062008-10-31 00:13:20 +0000358 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
359 os << "Address of stack memory associated with a compound literal "
360 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000361 << BR.getSourceManager()
362 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000363 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000364
Ted Kremenek8aed8062008-10-31 00:13:20 +0000365 R = CL->getSourceRange();
366 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000367 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
368 const Expr* ARE = AR->getExpr();
369 SourceLocation L = ARE->getLocStart();
370 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000371
Ted Kremenekde8cd192008-11-02 00:35:25 +0000372 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000373 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000374 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000375 }
376 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000377 os << "Address of stack memory associated with local variable '"
378 << V.getRegion()->getString() << "' returned.";
379 }
Mike Stump1eb44332009-09-09 15:08:12 +0000380
Ted Kremenekcf118d42009-02-04 23:49:09 +0000381 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
382 report->addRange(E->getSourceRange());
383 if (R.isValid()) report->addRange(R);
384 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000385 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000386 }
387};
Mike Stump1eb44332009-09-09 15:08:12 +0000388
Ted Kremenek5917d782008-11-21 00:27:44 +0000389class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
390public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000391 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
392 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000393
Ted Kremenekcf118d42009-02-04 23:49:09 +0000394 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000395 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
396 }
Mike Stump1eb44332009-09-09 15:08:12 +0000397
Ted Kremenek0c313172009-05-13 19:16:35 +0000398 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000399 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000400 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000401 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000402 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000403};
Ted Kremenek78d46242008-07-22 16:21:24 +0000404
405class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
406 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000407 GRStateManager& VM;
408 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000409
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000410 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000411
412 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000413 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000414 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000415
Ted Kremenekb7714b22008-07-30 17:49:12 +0000416 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000417 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
418 Expr* E2 = FindExpr(ExI);
419 if (E2) return E2;
420 }
Mike Stump1eb44332009-09-09 15:08:12 +0000421
Ted Kremenek78d46242008-07-22 16:21:24 +0000422 return Ex;
423 }
Mike Stump1eb44332009-09-09 15:08:12 +0000424
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000425 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000426 };
Mike Stump1eb44332009-09-09 15:08:12 +0000427
Ted Kremenek78d46242008-07-22 16:21:24 +0000428public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000429 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000430 : BuiltinBug(eng,"Use of garbage value",
431 "Branch condition evaluates to an undefined or garbage value")
432 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000433
Ted Kremenekcf118d42009-02-04 23:49:09 +0000434 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000435 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
436 E=Eng.undef_branches_end(); I!=E; ++I) {
437
438 // What's going on here: we want to highlight the subexpression of the
439 // condition that is the most likely source of the "uninitialized
440 // branch condition." We do a recursive walk of the condition's
441 // subexpressions and roughly look for the most nested subexpression
442 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000443 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
444 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
445 assert (Ex && "Block must have a terminator.");
446
447 // Get the predecessor node and check if is a PostStmt with the Stmt
448 // being the terminator condition. We want to inspect the state
449 // of that node instead because it will contain main information about
450 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000451 assert (!(*I)->pred_empty());
452
453 // Note: any predecessor will do. They should have identical state,
454 // since all the BlockEdge did was act as an error sink since the value
455 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000456 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000457 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000458 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000459
460 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
461 if (PS->getStmt() == Ex)
462 St = N->getState();
463
464 FindUndefExpr FindIt(Eng.getStateManager(), St);
465 Ex = FindIt.FindExpr(Ex);
466
Ted Kremenek85ac9342009-05-15 05:25:09 +0000467 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000468 R->addRange(Ex->getSourceRange());
469 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000470 }
471 }
Mike Stump1eb44332009-09-09 15:08:12 +0000472
Ted Kremenek85ac9342009-05-15 05:25:09 +0000473 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000474 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000475 BuiltinBugReport *R) {
476 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
477 N);
478 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000479};
480
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000481class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
482public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000483 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000484 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000485 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000486
Ted Kremenekcf118d42009-02-04 23:49:09 +0000487 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000488 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
489 }
490};
Mike Stump1eb44332009-09-09 15:08:12 +0000491
Ted Kremenek159d2482008-12-09 00:44:16 +0000492class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000493public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000494 BadSizeVLA(GRExprEngine* eng) :
495 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000496
Ted Kremenekcf118d42009-02-04 23:49:09 +0000497 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000498 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000499 I = Eng.ExplicitBadSizedVLA.begin(),
500 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
501
502 // Determine whether this was a 'zero-sized' VLA or a VLA with an
503 // undefined size.
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000504 ExplodedNode* N = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000505 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000506 const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
Ted Kremenekefd59942008-12-08 22:47:34 +0000507 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
508 QualType T = Eng.getContext().getCanonicalType(VD->getType());
509 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000510 Expr* SizeExpr = VT->getSizeExpr();
Mike Stump1eb44332009-09-09 15:08:12 +0000511
Ted Kremenek159d2482008-12-09 00:44:16 +0000512 std::string buf;
513 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000514 os << "The expression used to specify the number of elements in the "
515 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000516 << VD->getNameAsString() << "' evaluates to ";
Mike Stump1eb44332009-09-09 15:08:12 +0000517
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000518 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Mike Stump1eb44332009-09-09 15:08:12 +0000519
Ted Kremenekd49967f2009-04-29 21:58:13 +0000520 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000521 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000522 else
523 os << "0. VLAs with no elements have undefined behavior.";
Mike Stump1eb44332009-09-09 15:08:12 +0000524
Ted Kremenekd49967f2009-04-29 21:58:13 +0000525 std::string shortBuf;
526 llvm::raw_string_ostream os_short(shortBuf);
527 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000528 << (isUndefined ? "garbage value for array size"
529 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000530
Ted Kremenek85ac9342009-05-15 05:25:09 +0000531 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
532 os.str().c_str(), N, SizeExpr);
533
Ted Kremenekcf118d42009-02-04 23:49:09 +0000534 report->addRange(SizeExpr->getSourceRange());
535 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000536 }
537 }
Mike Stump1eb44332009-09-09 15:08:12 +0000538
Ted Kremenek85ac9342009-05-15 05:25:09 +0000539 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000540 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000541 BuiltinBugReport *R) {
542 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
543 N);
544 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000545};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000546
Ted Kremenek78d46242008-07-22 16:21:24 +0000547//===----------------------------------------------------------------------===//
548// __attribute__(nonnull) checking
549
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000550class VISIBILITY_HIDDEN CheckAttrNonNull :
551 public CheckerVisitor<CheckAttrNonNull> {
552
Ted Kremenekcf118d42009-02-04 23:49:09 +0000553 BugType *BT;
Mike Stump1eb44332009-09-09 15:08:12 +0000554
Ted Kremenek78d46242008-07-22 16:21:24 +0000555public:
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000556 CheckAttrNonNull() : BT(0) {}
Ted Kremenek31112182009-07-24 00:40:31 +0000557 ~CheckAttrNonNull() {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000558
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000559 static void *getTag() {
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000560 static int x = 0;
561 return &x;
562 }
563
564 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
565 const GRState *state = C.getState();
566 const GRState *originalState = state;
Mike Stump1eb44332009-09-09 15:08:12 +0000567
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000568 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000569 SVal X = state->getSVal(CE->getCallee());
Mike Stump1eb44332009-09-09 15:08:12 +0000570
Zhongxing Xu369f4472009-04-20 05:24:46 +0000571 const FunctionDecl* FD = X.getAsFunctionDecl();
572 if (!FD)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000573 return;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000574
Mike Stump1eb44332009-09-09 15:08:12 +0000575 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000576 if (!Att)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000577 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000578
Ted Kremenek78d46242008-07-22 16:21:24 +0000579 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000580 unsigned idx = 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000581
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000582 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
Ted Kremenek78d46242008-07-22 16:21:24 +0000583 ++I, ++idx) {
Mike Stump1eb44332009-09-09 15:08:12 +0000584
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000585 if (!Att->isNonNull(idx))
586 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000587
Ted Kremenek08780072009-08-24 22:47:34 +0000588 const SVal &V = state->getSVal(*I);
589 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
Mike Stump1eb44332009-09-09 15:08:12 +0000590
Ted Kremenek08780072009-08-24 22:47:34 +0000591 if (!DV)
592 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000593
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000594 ConstraintManager &CM = C.getConstraintManager();
595 const GRState *stateNotNull, *stateNull;
Ted Kremenek08780072009-08-24 22:47:34 +0000596 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000597
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000598 if (stateNull && !stateNotNull) {
599 // Generate an error node. Check for a null node in case
600 // we cache out.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000601 if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000602
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000603 // Lazily allocate the BugType object if it hasn't already been
604 // created. Ownership is transferred to the BugReporter object once
605 // the BugReport is passed to 'EmitWarning'.
606 if (!BT)
607 BT = new BugType("Argument with 'nonnull' attribute passed null",
608 "API");
Mike Stump1eb44332009-09-09 15:08:12 +0000609
Ted Kremenek592362b2009-08-18 01:05:30 +0000610 EnhancedBugReport *R =
611 new EnhancedBugReport(*BT,
612 "Null pointer passed as an argument to a "
613 "'nonnull' parameter", errorNode);
Mike Stump1eb44332009-09-09 15:08:12 +0000614
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000615 // Highlight the range of the argument that was null.
Ted Kremenek592362b2009-08-18 01:05:30 +0000616 const Expr *arg = *I;
617 R->addRange(arg->getSourceRange());
618 R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
Mike Stump1eb44332009-09-09 15:08:12 +0000619
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000620 // Emit the bug report.
621 C.EmitReport(R);
622 }
Mike Stump1eb44332009-09-09 15:08:12 +0000623
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000624 // Always return. Either we cached out or we just emitted an error.
625 return;
626 }
Mike Stump1eb44332009-09-09 15:08:12 +0000627
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000628 // If a pointer value passed the check we should assume that it is
629 // indeed not null from this point forward.
630 assert(stateNotNull);
631 state = stateNotNull;
632 }
Mike Stump1eb44332009-09-09 15:08:12 +0000633
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000634 // If we reach here all of the arguments passed the nonnull check.
635 // If 'state' has been updated generated a new node.
636 if (state != originalState)
Zhongxing Xu6403b572009-09-02 13:26:26 +0000637 C.addTransition(C.GenerateNode(CE, state));
Ted Kremenek78d46242008-07-22 16:21:24 +0000638 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000639};
Ted Kremenek78d46242008-07-22 16:21:24 +0000640
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000641// Undefined arguments checking.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000642
Mike Stump1eb44332009-09-09 15:08:12 +0000643class VISIBILITY_HIDDEN CheckUndefinedArg
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000644 : public CheckerVisitor<CheckUndefinedArg> {
645
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000646 BadArg *BT;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000647
648public:
649 CheckUndefinedArg() : BT(0) {}
650 ~CheckUndefinedArg() {}
651
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000652 static void *getTag() {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000653 static int x = 0;
654 return &x;
655 }
656
657 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
658};
659
660void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
661 for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
662 I != E; ++I) {
663 if (C.getState()->getSVal(*I).isUndef()) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000664 if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000665 if (!BT)
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000666 BT = new BadArg();
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000667 // Generate a report for this bug.
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000668 ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000669 ErrorNode, *I);
670 Report->addRange((*I)->getSourceRange());
671 C.EmitReport(Report);
672 }
673 }
674 }
675}
676
Zhongxing Xud99f3612009-09-02 08:10:35 +0000677class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
678 BadCall *BT;
679
680public:
681 CheckBadCall() : BT(0) {}
682 ~CheckBadCall() {}
683
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000684 static void *getTag() {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000685 static int x = 0;
686 return &x;
687 }
688
689 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
690};
691
692void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
693 const Expr *Callee = CE->getCallee()->IgnoreParens();
694 SVal L = C.getState()->getSVal(Callee);
695
696 if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000697 if (ExplodedNode *N = C.GenerateNode(CE, true)) {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000698 if (!BT)
699 BT = new BadCall();
700 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
701 }
702 }
703}
704
Zhongxing Xu524e4652009-10-22 01:58:10 +0000705class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000706 DivZero *BT;
707public:
Zhongxing Xu524e4652009-10-22 01:58:10 +0000708 CheckDivZero() : BT(0) {}
709 ~CheckDivZero() {}
Zhongxing Xu6403b572009-09-02 13:26:26 +0000710
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000711 static void *getTag() {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000712 static int x;
713 return &x;
714 }
715
716 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
717};
718
Zhongxing Xu524e4652009-10-22 01:58:10 +0000719void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
720 const BinaryOperator *B) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000721 BinaryOperator::Opcode Op = B->getOpcode();
722 if (Op != BinaryOperator::Div &&
723 Op != BinaryOperator::Rem &&
724 Op != BinaryOperator::DivAssign &&
725 Op != BinaryOperator::RemAssign)
726 return;
727
728 if (!B->getRHS()->getType()->isIntegerType() ||
729 !B->getRHS()->getType()->isScalarType())
730 return;
731
Zhongxing Xu6403b572009-09-02 13:26:26 +0000732 SVal Denom = C.getState()->getSVal(B->getRHS());
Ted Kremenek970e03a2009-09-03 01:48:03 +0000733 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
734
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000735 // Divide-by-undefined handled in the generic checking for uses of
736 // undefined values.
Mike Stump1eb44332009-09-09 15:08:12 +0000737 if (!DV)
Ted Kremenek970e03a2009-09-03 01:48:03 +0000738 return;
739
Zhongxing Xu6403b572009-09-02 13:26:26 +0000740 // Check for divide by zero.
741 ConstraintManager &CM = C.getConstraintManager();
742 const GRState *stateNotZero, *stateZero;
Ted Kremenek970e03a2009-09-03 01:48:03 +0000743 llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000744
Zhongxing Xu6403b572009-09-02 13:26:26 +0000745 if (stateZero && !stateNotZero) {
746 if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
747 if (!BT)
748 BT = new DivZero();
Mike Stump1eb44332009-09-09 15:08:12 +0000749
Zhongxing Xu6403b572009-09-02 13:26:26 +0000750 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
751 }
752 return;
753 }
754
Zhongxing Xu524e4652009-10-22 01:58:10 +0000755 // If we get here, then the denom should not be zero. We abandon the implicit
756 // zero denom case for now.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000757 if (stateNotZero != C.getState())
758 C.addTransition(C.GenerateNode(B, stateNotZero));
759}
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000760
761class VISIBILITY_HIDDEN CheckUndefDeref : public Checker {
762 UndefinedDeref *BT;
763public:
764 CheckUndefDeref() : BT(0) {}
765
Ted Kremenek3f214b32009-10-29 05:33:39 +0000766 ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000767 const GRState *state, SVal V, GRExprEngine &Eng);
768
769 static void *getTag() {
770 static int x = 0;
771 return &x;
772 }
773};
774
Ted Kremenek3f214b32009-10-29 05:33:39 +0000775ExplodedNode *CheckUndefDeref::CheckLocation(const Stmt *S, ExplodedNode *Pred,
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000776 const GRState *state, SVal V,
777 GRExprEngine &Eng) {
778 GRStmtNodeBuilder &Builder = Eng.getBuilder();
779 BugReporter &BR = Eng.getBugReporter();
780
781 if (V.isUndef()) {
782 ExplodedNode *N = Builder.generateNode(S, state, Pred,
783 ProgramPoint::PostUndefLocationCheckFailedKind);
784 if (N) {
785 if (!BT)
786 BT = new UndefinedDeref();
787
788 N->markAsSink();
789 BR.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
790 }
791 return 0;
792 }
793
794 return Pred;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000795}
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000796
797ExplodedNode *NullDerefChecker::CheckLocation(const Stmt *S, ExplodedNode *Pred,
798 const GRState *state, SVal V,
799 GRExprEngine &Eng) {
800 Loc *LV = dyn_cast<Loc>(&V);
801
802 // If the value is not a location, don't touch the node.
803 if (!LV)
804 return Pred;
805
806 const GRState *NotNullState = state->Assume(*LV, true);
807 const GRState *NullState = state->Assume(*LV, false);
808
809 GRStmtNodeBuilder &Builder = Eng.getBuilder();
810 BugReporter &BR = Eng.getBugReporter();
811
812 // The explicit NULL case.
813 if (NullState) {
814 // Use the GDM to mark in the state what lval was null.
815 const SVal *PersistentLV = Eng.getBasicVals().getPersistentSVal(*LV);
816 NullState = NullState->set<GRState::NullDerefTag>(PersistentLV);
817
818 ExplodedNode *N = Builder.generateNode(S, NullState, Pred,
819 ProgramPoint::PostNullCheckFailedKind);
820 if (N) {
821 N->markAsSink();
822
823 if (!NotNullState) { // Explicit null case.
824 if (!BT)
825 BT = new NullDeref();
826 BR.EmitReport(new BuiltinBugReport(*BT,BT->getDescription().c_str(),N));
827 return 0;
828 } else // Implicit null case.
829 ImplicitNullDerefNodes.push_back(N);
830 }
831 }
832
833 if (!NotNullState)
834 return 0;
835 return Builder.generateNode(S, NotNullState, Pred,
836 ProgramPoint::PostLocationChecksSucceedKind);
837}
838} // end clang namespace
Ted Kremenek78d46242008-07-22 16:21:24 +0000839//===----------------------------------------------------------------------===//
840// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000841//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000842
843void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000844 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
845 // are different than what probably many checks will do since they don't
846 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
847 // analyzing a function. Generation of BugReport objects is done via a call
848 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000849 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000850 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000851 BR.Register(new RetStack(this));
852 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000853 BR.Register(new BadMsgExprArg(this));
854 BR.Register(new BadReceiver(this));
855 BR.Register(new OutOfBoundMemoryAccess(this));
856 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000857 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000858 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000859
Ted Kremenekcf118d42009-02-04 23:49:09 +0000860 // The following checks do not need to have their associated BugTypes
861 // explicitly registered with the BugReporter. If they issue any BugReports,
862 // their associated BugType will get registered with the BugReporter
863 // automatically. Note that the check itself is owned by the GRExprEngine
864 // object.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000865 registerCheck<CheckAttrNonNull>(new CheckAttrNonNull());
866 registerCheck<CheckUndefinedArg>(new CheckUndefinedArg());
867 registerCheck<CheckBadCall>(new CheckBadCall());
868 registerCheck<CheckDivZero>(new CheckDivZero());
869 registerCheck<CheckUndefDeref>(new CheckUndefDeref());
870 registerCheck<NullDerefChecker>(new NullDerefChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000871}