blob: 630e617a095a0b3f30f64eb94600b94b53fd19cc [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 Kremenekd86caaa2009-10-30 17:28:40 +000018#include "clang/Analysis/PathSensitive/Checkers/NullDerefChecker.h"
Zhongxing Xu246a9ad2009-10-31 08:44:33 +000019#include "clang/Analysis/PathSensitive/Checkers/UndefDerefChecker.h"
Zhongxing Xu9e56d232009-10-31 10:02:37 +000020#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
Zhongxing Xu4f64e5f2009-11-03 05:48:04 +000021#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000022#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000023#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000024#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000025#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000026
27using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000028using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000029
30//===----------------------------------------------------------------------===//
31// Utility functions.
32//===----------------------------------------------------------------------===//
33
34template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000035ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000036 return *I;
37}
38
39template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000040ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000041 return I->first;
42}
43
44//===----------------------------------------------------------------------===//
45// Bug Descriptions.
46//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000047namespace clang {
48class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000049public:
50 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000051 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000052 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000053
Ted Kremenek85ac9342009-05-15 05:25:09 +000054 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000055 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000056 : RangedBugReport(bt, shortDesc, desc, n) {}
57
Ted Kremenekdd986cc2009-05-07 00:45:33 +000058 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000059 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000060};
61
Zhongxing Xuec9227f2009-10-29 02:09:30 +000062void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
63 const ExplodedNode* N) {
64 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
65}
Mike Stump1eb44332009-09-09 15:08:12 +000066
Ted Kremenekdd986cc2009-05-07 00:45:33 +000067template <typename ITER>
68void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
69 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
70 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000071}
Mike Stump1eb44332009-09-09 15:08:12 +000072
Ted Kremenek0c313172009-05-13 19:16:35 +000073class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000074public:
75 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000076 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000077
Ted Kremenek0c313172009-05-13 19:16:35 +000078 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000079 for (GRExprEngine::nil_receiver_struct_ret_iterator
80 I=Eng.nil_receiver_struct_ret_begin(),
81 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
82
83 std::string sbuf;
84 llvm::raw_string_ostream os(sbuf);
85 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000086 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000087 os << "The receiver in the message expression is 'nil' and results in the"
88 " returned value (of type '"
89 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000090 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000091
Ted Kremenek0c313172009-05-13 19:16:35 +000092 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000093 R->addRange(ME->getReceiver()->getSourceRange());
94 BR.EmitReport(R);
95 }
96 }
Mike Stump1eb44332009-09-09 15:08:12 +000097
Ted Kremenek0c313172009-05-13 19:16:35 +000098 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000099 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000100 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000101 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000102 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000103};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000104
Ted Kremenek0c313172009-05-13 19:16:35 +0000105class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000106public:
107 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000108 BuiltinBug(eng,
109 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000110
Ted Kremenek0c313172009-05-13 19:16:35 +0000111 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000112 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
113 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
114 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000115
Ted Kremenek899b3de2009-04-08 03:07:17 +0000116 std::string sbuf;
117 llvm::raw_string_ostream os(sbuf);
118 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000119 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000120 os << "The receiver in the message expression is 'nil' and results in the"
121 " returned value (of type '"
122 << ME->getType().getAsString()
123 << "' and of size "
124 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000125 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000126
Ted Kremenek0c313172009-05-13 19:16:35 +0000127 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000128 R->addRange(ME->getReceiver()->getSourceRange());
129 BR.EmitReport(R);
130 }
Mike Stump1eb44332009-09-09 15:08:12 +0000131 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000132 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000133 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000134 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000135 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000136 }
137};
Mike Stump1eb44332009-09-09 15:08:12 +0000138
Ted Kremenek78d46242008-07-22 16:21:24 +0000139class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
140public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000141 UndefResult(GRExprEngine* eng)
142 : BuiltinBug(eng,"Undefined or garbage result",
143 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000144
Ted Kremenekcf118d42009-02-04 23:49:09 +0000145 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000146 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
147 E = Eng.undef_results_end(); I!=E; ++I) {
148
149 ExplodedNode *N = *I;
150 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
151 BuiltinBugReport *report = NULL;
152
153 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
154 llvm::SmallString<256> sbuf;
155 llvm::raw_svector_ostream OS(sbuf);
156 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000157 const Expr *Ex = NULL;
158 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000159
160 if (ST->getSVal(B->getLHS()).isUndef()) {
161 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000162 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000163 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000164 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000165 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000166 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000167 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000168
169 if (Ex) {
170 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000171 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000172 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000173 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000174 }
175 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000176 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000177 OS << "The result of the '"
178 << BinaryOperator::getOpcodeStr(B->getOpcode())
179 << "' expression is undefined";
180 }
181
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000182 // FIXME: Use StringRefs to pass string information.
183 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000184 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000185 }
186 else {
187 report = new BuiltinBugReport(*this,
188 "Expression evaluates to an uninitialized"
189 " or undefined value", N);
190 }
191
192 BR.EmitReport(report);
193 }
194 }
195
196 void registerInitialVisitors(BugReporterContext& BRC,
197 const ExplodedNode* N,
198 BuiltinBugReport *R) {
199
200 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
201 const Stmt *X = S;
202
203 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
204 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000205 if (ST->getSVal(B->getLHS()).isUndef())
206 X = B->getLHS();
207 else if (ST->getSVal(B->getRHS()).isUndef())
208 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000209 }
210
211 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000212 }
213};
Mike Stump1eb44332009-09-09 15:08:12 +0000214
Ted Kremenek85ac9342009-05-15 05:25:09 +0000215class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
216 const Stmt *Arg;
217public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000218 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000219 const Stmt *arg)
220 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000221
Ted Kremenek85ac9342009-05-15 05:25:09 +0000222 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000223 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000224 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
225
226 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000227};
228
229class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000230public:
231 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000232 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000233
Ted Kremenekcf118d42009-02-04 23:49:09 +0000234 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000235 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000236
Ted Kremenek85ac9342009-05-15 05:25:09 +0000237 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000238 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000239 BuiltinBugReport *R) {
240 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
241 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000242 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000243};
Mike Stump1eb44332009-09-09 15:08:12 +0000244
Ted Kremenek78d46242008-07-22 16:21:24 +0000245class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
246public:
Mike Stump1eb44332009-09-09 15:08:12 +0000247 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000248 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000249
Ted Kremenekcf118d42009-02-04 23:49:09 +0000250 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000251 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000252 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000253 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000254 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
255 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000256 report->addRange(I->second->getSourceRange());
257 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000258 }
259 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000260};
Mike Stump1eb44332009-09-09 15:08:12 +0000261
Ted Kremenek78d46242008-07-22 16:21:24 +0000262class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000263public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000264 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000265 : BuiltinBug(eng,"Uninitialized receiver",
266 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000267
Ted Kremenekcf118d42009-02-04 23:49:09 +0000268 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000269 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000270 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000271
Ted Kremenek78d46242008-07-22 16:21:24 +0000272 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000273 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000274 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000275 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
276 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000277 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000278 report->addRange(E->getSourceRange());
279 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000280 }
281 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000282
Ted Kremenek0c313172009-05-13 19:16:35 +0000283 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000284 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000285 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000286 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000287 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000288};
Ted Kremenek5917d782008-11-21 00:27:44 +0000289
Ted Kremenek78d46242008-07-22 16:21:24 +0000290class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
291public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000292 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000293 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000294
Ted Kremenekcf118d42009-02-04 23:49:09 +0000295 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000296 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
297 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000298
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000299 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000300 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
301 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
302 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000303
Ted Kremenek22bda882008-07-31 20:31:27 +0000304 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000305 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000306
Ted Kremenek22bda882008-07-31 20:31:27 +0000307 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000308 std::string buf;
309 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000310 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000311
Ted Kremenek8aed8062008-10-31 00:13:20 +0000312 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000313 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000314 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000315
Ted Kremenek8aed8062008-10-31 00:13:20 +0000316 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
317 os << "Address of stack memory associated with a compound literal "
318 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000319 << BR.getSourceManager()
320 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000321 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000322
Ted Kremenek8aed8062008-10-31 00:13:20 +0000323 R = CL->getSourceRange();
324 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000325 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
326 const Expr* ARE = AR->getExpr();
327 SourceLocation L = ARE->getLocStart();
328 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000329
Ted Kremenekde8cd192008-11-02 00:35:25 +0000330 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000331 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000332 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000333 }
334 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000335 os << "Address of stack memory associated with local variable '"
336 << V.getRegion()->getString() << "' returned.";
337 }
Mike Stump1eb44332009-09-09 15:08:12 +0000338
Ted Kremenekcf118d42009-02-04 23:49:09 +0000339 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
340 report->addRange(E->getSourceRange());
341 if (R.isValid()) report->addRange(R);
342 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000343 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000344 }
345};
Mike Stump1eb44332009-09-09 15:08:12 +0000346
Ted Kremenek5917d782008-11-21 00:27:44 +0000347class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
348public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000349 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
350 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000351
Ted Kremenekcf118d42009-02-04 23:49:09 +0000352 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000353 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
354 }
Mike Stump1eb44332009-09-09 15:08:12 +0000355
Ted Kremenek0c313172009-05-13 19:16:35 +0000356 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000357 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000358 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000359 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000360 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000361};
Ted Kremenek78d46242008-07-22 16:21:24 +0000362
363class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
364 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000365 GRStateManager& VM;
366 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000367
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000368 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000369
370 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000371 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000372 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000373
Ted Kremenekb7714b22008-07-30 17:49:12 +0000374 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000375 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
376 Expr* E2 = FindExpr(ExI);
377 if (E2) return E2;
378 }
Mike Stump1eb44332009-09-09 15:08:12 +0000379
Ted Kremenek78d46242008-07-22 16:21:24 +0000380 return Ex;
381 }
Mike Stump1eb44332009-09-09 15:08:12 +0000382
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000383 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000384 };
Mike Stump1eb44332009-09-09 15:08:12 +0000385
Ted Kremenek78d46242008-07-22 16:21:24 +0000386public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000387 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000388 : BuiltinBug(eng,"Use of garbage value",
389 "Branch condition evaluates to an undefined or garbage value")
390 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000391
Ted Kremenekcf118d42009-02-04 23:49:09 +0000392 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000393 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
394 E=Eng.undef_branches_end(); I!=E; ++I) {
395
396 // What's going on here: we want to highlight the subexpression of the
397 // condition that is the most likely source of the "uninitialized
398 // branch condition." We do a recursive walk of the condition's
399 // subexpressions and roughly look for the most nested subexpression
400 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000401 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
402 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
403 assert (Ex && "Block must have a terminator.");
404
405 // Get the predecessor node and check if is a PostStmt with the Stmt
406 // being the terminator condition. We want to inspect the state
407 // of that node instead because it will contain main information about
408 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000409 assert (!(*I)->pred_empty());
410
411 // Note: any predecessor will do. They should have identical state,
412 // since all the BlockEdge did was act as an error sink since the value
413 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000414 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000415 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000416 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000417
418 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
419 if (PS->getStmt() == Ex)
420 St = N->getState();
421
422 FindUndefExpr FindIt(Eng.getStateManager(), St);
423 Ex = FindIt.FindExpr(Ex);
424
Ted Kremenek85ac9342009-05-15 05:25:09 +0000425 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000426 R->addRange(Ex->getSourceRange());
427 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000428 }
429 }
Mike Stump1eb44332009-09-09 15:08:12 +0000430
Ted Kremenek85ac9342009-05-15 05:25:09 +0000431 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000432 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000433 BuiltinBugReport *R) {
434 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
435 N);
436 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000437};
438
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000439class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
440public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000441 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000442 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000443 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000444
Ted Kremenekcf118d42009-02-04 23:49:09 +0000445 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000446 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
447 }
448};
Mike Stump1eb44332009-09-09 15:08:12 +0000449
Ted Kremenek159d2482008-12-09 00:44:16 +0000450class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000451public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000452 BadSizeVLA(GRExprEngine* eng) :
453 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000454
Ted Kremenekcf118d42009-02-04 23:49:09 +0000455 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000456 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000457 I = Eng.ExplicitBadSizedVLA.begin(),
458 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
459
460 // Determine whether this was a 'zero-sized' VLA or a VLA with an
461 // undefined size.
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000462 ExplodedNode* N = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000463 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000464 const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
Ted Kremenekefd59942008-12-08 22:47:34 +0000465 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
466 QualType T = Eng.getContext().getCanonicalType(VD->getType());
467 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000468 Expr* SizeExpr = VT->getSizeExpr();
Mike Stump1eb44332009-09-09 15:08:12 +0000469
Ted Kremenek159d2482008-12-09 00:44:16 +0000470 std::string buf;
471 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000472 os << "The expression used to specify the number of elements in the "
473 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000474 << VD->getNameAsString() << "' evaluates to ";
Mike Stump1eb44332009-09-09 15:08:12 +0000475
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000476 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Mike Stump1eb44332009-09-09 15:08:12 +0000477
Ted Kremenekd49967f2009-04-29 21:58:13 +0000478 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000479 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000480 else
481 os << "0. VLAs with no elements have undefined behavior.";
Mike Stump1eb44332009-09-09 15:08:12 +0000482
Ted Kremenekd49967f2009-04-29 21:58:13 +0000483 std::string shortBuf;
484 llvm::raw_string_ostream os_short(shortBuf);
485 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000486 << (isUndefined ? "garbage value for array size"
487 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000488
Ted Kremenek85ac9342009-05-15 05:25:09 +0000489 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
490 os.str().c_str(), N, SizeExpr);
491
Ted Kremenekcf118d42009-02-04 23:49:09 +0000492 report->addRange(SizeExpr->getSourceRange());
493 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000494 }
495 }
Mike Stump1eb44332009-09-09 15:08:12 +0000496
Ted Kremenek85ac9342009-05-15 05:25:09 +0000497 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000498 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000499 BuiltinBugReport *R) {
500 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
501 N);
502 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000503};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000504
Ted Kremenek78d46242008-07-22 16:21:24 +0000505//===----------------------------------------------------------------------===//
506// __attribute__(nonnull) checking
507
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000508class VISIBILITY_HIDDEN CheckAttrNonNull :
509 public CheckerVisitor<CheckAttrNonNull> {
510
Ted Kremenekcf118d42009-02-04 23:49:09 +0000511 BugType *BT;
Mike Stump1eb44332009-09-09 15:08:12 +0000512
Ted Kremenek78d46242008-07-22 16:21:24 +0000513public:
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000514 CheckAttrNonNull() : BT(0) {}
Ted Kremenek31112182009-07-24 00:40:31 +0000515 ~CheckAttrNonNull() {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000516
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000517 static void *getTag() {
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000518 static int x = 0;
519 return &x;
520 }
521
522 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
523 const GRState *state = C.getState();
524 const GRState *originalState = state;
Mike Stump1eb44332009-09-09 15:08:12 +0000525
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000526 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000527 SVal X = state->getSVal(CE->getCallee());
Mike Stump1eb44332009-09-09 15:08:12 +0000528
Zhongxing Xu369f4472009-04-20 05:24:46 +0000529 const FunctionDecl* FD = X.getAsFunctionDecl();
530 if (!FD)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000531 return;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000532
Mike Stump1eb44332009-09-09 15:08:12 +0000533 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000534 if (!Att)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000535 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000536
Ted Kremenek78d46242008-07-22 16:21:24 +0000537 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000538 unsigned idx = 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000539
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000540 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
Ted Kremenek78d46242008-07-22 16:21:24 +0000541 ++I, ++idx) {
Mike Stump1eb44332009-09-09 15:08:12 +0000542
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000543 if (!Att->isNonNull(idx))
544 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000545
Ted Kremenek08780072009-08-24 22:47:34 +0000546 const SVal &V = state->getSVal(*I);
547 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
Mike Stump1eb44332009-09-09 15:08:12 +0000548
Ted Kremenek08780072009-08-24 22:47:34 +0000549 if (!DV)
550 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000551
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000552 ConstraintManager &CM = C.getConstraintManager();
553 const GRState *stateNotNull, *stateNull;
Ted Kremenek08780072009-08-24 22:47:34 +0000554 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000555
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000556 if (stateNull && !stateNotNull) {
557 // Generate an error node. Check for a null node in case
558 // we cache out.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000559 if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000560
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000561 // Lazily allocate the BugType object if it hasn't already been
562 // created. Ownership is transferred to the BugReporter object once
563 // the BugReport is passed to 'EmitWarning'.
564 if (!BT)
565 BT = new BugType("Argument with 'nonnull' attribute passed null",
566 "API");
Mike Stump1eb44332009-09-09 15:08:12 +0000567
Ted Kremenek592362b2009-08-18 01:05:30 +0000568 EnhancedBugReport *R =
569 new EnhancedBugReport(*BT,
570 "Null pointer passed as an argument to a "
571 "'nonnull' parameter", errorNode);
Mike Stump1eb44332009-09-09 15:08:12 +0000572
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000573 // Highlight the range of the argument that was null.
Ted Kremenek592362b2009-08-18 01:05:30 +0000574 const Expr *arg = *I;
575 R->addRange(arg->getSourceRange());
576 R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
Mike Stump1eb44332009-09-09 15:08:12 +0000577
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000578 // Emit the bug report.
579 C.EmitReport(R);
580 }
Mike Stump1eb44332009-09-09 15:08:12 +0000581
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000582 // Always return. Either we cached out or we just emitted an error.
583 return;
584 }
Mike Stump1eb44332009-09-09 15:08:12 +0000585
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000586 // If a pointer value passed the check we should assume that it is
587 // indeed not null from this point forward.
588 assert(stateNotNull);
589 state = stateNotNull;
590 }
Mike Stump1eb44332009-09-09 15:08:12 +0000591
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000592 // If we reach here all of the arguments passed the nonnull check.
593 // If 'state' has been updated generated a new node.
594 if (state != originalState)
Zhongxing Xu6403b572009-09-02 13:26:26 +0000595 C.addTransition(C.GenerateNode(CE, state));
Ted Kremenek78d46242008-07-22 16:21:24 +0000596 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000597};
Ted Kremenek78d46242008-07-22 16:21:24 +0000598
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000599// Undefined arguments checking.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000600
Mike Stump1eb44332009-09-09 15:08:12 +0000601class VISIBILITY_HIDDEN CheckUndefinedArg
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000602 : public CheckerVisitor<CheckUndefinedArg> {
603
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000604 BadArg *BT;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000605
606public:
607 CheckUndefinedArg() : BT(0) {}
608 ~CheckUndefinedArg() {}
609
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000610 static void *getTag() {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000611 static int x = 0;
612 return &x;
613 }
614
615 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
616};
617
618void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
619 for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
620 I != E; ++I) {
621 if (C.getState()->getSVal(*I).isUndef()) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000622 if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000623 if (!BT)
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000624 BT = new BadArg();
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000625 // Generate a report for this bug.
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000626 ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000627 ErrorNode, *I);
628 Report->addRange((*I)->getSourceRange());
629 C.EmitReport(Report);
630 }
631 }
632 }
633}
634
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000635} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000636
Ted Kremenek78d46242008-07-22 16:21:24 +0000637//===----------------------------------------------------------------------===//
638// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000639//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000640
641void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000642 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
643 // are different than what probably many checks will do since they don't
644 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
645 // analyzing a function. Generation of BugReport objects is done via a call
646 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000647 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000648 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000649 BR.Register(new RetStack(this));
650 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000651 BR.Register(new BadMsgExprArg(this));
652 BR.Register(new BadReceiver(this));
653 BR.Register(new OutOfBoundMemoryAccess(this));
654 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000655 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000656 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000657
Ted Kremenekcf118d42009-02-04 23:49:09 +0000658 // The following checks do not need to have their associated BugTypes
659 // explicitly registered with the BugReporter. If they issue any BugReports,
660 // their associated BugType will get registered with the BugReporter
661 // automatically. Note that the check itself is owned by the GRExprEngine
662 // object.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000663 registerCheck<CheckAttrNonNull>(new CheckAttrNonNull());
664 registerCheck<CheckUndefinedArg>(new CheckUndefinedArg());
Zhongxing Xu4f64e5f2009-11-03 05:48:04 +0000665 registerCheck<BadCallChecker>(new BadCallChecker());
Zhongxing Xu9e56d232009-10-31 10:02:37 +0000666 registerCheck<DivZeroChecker>(new DivZeroChecker());
Zhongxing Xu246a9ad2009-10-31 08:44:33 +0000667 registerCheck<UndefDerefChecker>(new UndefDerefChecker());
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000668 registerCheck<NullDerefChecker>(new NullDerefChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000669}