blob: 025d2b3bdb85a57484ea1cee939af47bf1e03ccc [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"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000021#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000022#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000023#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000024#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000025
26using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000027using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000028
29//===----------------------------------------------------------------------===//
30// Utility functions.
31//===----------------------------------------------------------------------===//
32
33template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000034ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000035 return *I;
36}
37
38template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000039ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000040 return I->first;
41}
42
43//===----------------------------------------------------------------------===//
44// Bug Descriptions.
45//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000046namespace clang {
47class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000048public:
49 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000050 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000051 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000052
Ted Kremenek85ac9342009-05-15 05:25:09 +000053 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000054 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000055 : RangedBugReport(bt, shortDesc, desc, n) {}
56
Ted Kremenekdd986cc2009-05-07 00:45:33 +000057 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000058 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000059};
60
Zhongxing Xuec9227f2009-10-29 02:09:30 +000061void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
62 const ExplodedNode* N) {
63 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
64}
Mike Stump1eb44332009-09-09 15:08:12 +000065
Ted Kremenekdd986cc2009-05-07 00:45:33 +000066template <typename ITER>
67void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
68 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
69 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000070}
Mike Stump1eb44332009-09-09 15:08:12 +000071
Ted Kremenek0c313172009-05-13 19:16:35 +000072class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000073public:
74 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000075 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000076
Ted Kremenek0c313172009-05-13 19:16:35 +000077 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000078 for (GRExprEngine::nil_receiver_struct_ret_iterator
79 I=Eng.nil_receiver_struct_ret_begin(),
80 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
81
82 std::string sbuf;
83 llvm::raw_string_ostream os(sbuf);
84 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000085 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000086 os << "The receiver in the message expression is 'nil' and results in the"
87 " returned value (of type '"
88 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000089 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000090
Ted Kremenek0c313172009-05-13 19:16:35 +000091 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000092 R->addRange(ME->getReceiver()->getSourceRange());
93 BR.EmitReport(R);
94 }
95 }
Mike Stump1eb44332009-09-09 15:08:12 +000096
Ted Kremenek0c313172009-05-13 19:16:35 +000097 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000098 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +000099 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000100 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000101 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000102};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000103
Ted Kremenek0c313172009-05-13 19:16:35 +0000104class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000105public:
106 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000107 BuiltinBug(eng,
108 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000109
Ted Kremenek0c313172009-05-13 19:16:35 +0000110 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000111 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
112 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
113 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000114
Ted Kremenek899b3de2009-04-08 03:07:17 +0000115 std::string sbuf;
116 llvm::raw_string_ostream os(sbuf);
117 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000118 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000119 os << "The receiver in the message expression is 'nil' and results in the"
120 " returned value (of type '"
121 << ME->getType().getAsString()
122 << "' and of size "
123 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000124 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000125
Ted Kremenek0c313172009-05-13 19:16:35 +0000126 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000127 R->addRange(ME->getReceiver()->getSourceRange());
128 BR.EmitReport(R);
129 }
Mike Stump1eb44332009-09-09 15:08:12 +0000130 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000131 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000132 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000133 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000134 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000135 }
136};
Mike Stump1eb44332009-09-09 15:08:12 +0000137
Ted Kremenek78d46242008-07-22 16:21:24 +0000138class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
139public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000140 UndefResult(GRExprEngine* eng)
141 : BuiltinBug(eng,"Undefined or garbage result",
142 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000143
Ted Kremenekcf118d42009-02-04 23:49:09 +0000144 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000145 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
146 E = Eng.undef_results_end(); I!=E; ++I) {
147
148 ExplodedNode *N = *I;
149 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
150 BuiltinBugReport *report = NULL;
151
152 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
153 llvm::SmallString<256> sbuf;
154 llvm::raw_svector_ostream OS(sbuf);
155 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000156 const Expr *Ex = NULL;
157 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000158
159 if (ST->getSVal(B->getLHS()).isUndef()) {
160 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000161 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000162 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000163 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000164 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000165 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000166 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000167
168 if (Ex) {
169 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000170 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000171 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000172 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000173 }
174 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000175 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000176 OS << "The result of the '"
177 << BinaryOperator::getOpcodeStr(B->getOpcode())
178 << "' expression is undefined";
179 }
180
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000181 // FIXME: Use StringRefs to pass string information.
182 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000183 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000184 }
185 else {
186 report = new BuiltinBugReport(*this,
187 "Expression evaluates to an uninitialized"
188 " or undefined value", N);
189 }
190
191 BR.EmitReport(report);
192 }
193 }
194
195 void registerInitialVisitors(BugReporterContext& BRC,
196 const ExplodedNode* N,
197 BuiltinBugReport *R) {
198
199 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
200 const Stmt *X = S;
201
202 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
203 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000204 if (ST->getSVal(B->getLHS()).isUndef())
205 X = B->getLHS();
206 else if (ST->getSVal(B->getRHS()).isUndef())
207 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000208 }
209
210 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000211 }
212};
Mike Stump1eb44332009-09-09 15:08:12 +0000213
Ted Kremenek78d46242008-07-22 16:21:24 +0000214class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
215public:
Zhongxing Xud99f3612009-09-02 08:10:35 +0000216 BadCall(GRExprEngine *eng = 0)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000217 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000218 "Called function pointer is a null or undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000219
Ted Kremenek85ac9342009-05-15 05:25:09 +0000220 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000221 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000222 BuiltinBugReport *R) {
223 registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
224 }
225};
226
227
228class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
229 const Stmt *Arg;
230public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000231 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000232 const Stmt *arg)
233 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000234
Ted Kremenek85ac9342009-05-15 05:25:09 +0000235 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000236 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000237 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
238
239 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000240};
241
242class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000243public:
244 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000245 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000246
Ted Kremenekcf118d42009-02-04 23:49:09 +0000247 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000248 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000249
Ted Kremenek85ac9342009-05-15 05:25:09 +0000250 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000251 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000252 BuiltinBugReport *R) {
253 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
254 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000255 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000256};
Mike Stump1eb44332009-09-09 15:08:12 +0000257
Ted Kremenek78d46242008-07-22 16:21:24 +0000258class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
259public:
Mike Stump1eb44332009-09-09 15:08:12 +0000260 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000261 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000262
Ted Kremenekcf118d42009-02-04 23:49:09 +0000263 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000264 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000265 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000266 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000267 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
268 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000269 report->addRange(I->second->getSourceRange());
270 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000271 }
272 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000273};
Mike Stump1eb44332009-09-09 15:08:12 +0000274
Ted Kremenek78d46242008-07-22 16:21:24 +0000275class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000276public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000277 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000278 : BuiltinBug(eng,"Uninitialized receiver",
279 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000280
Ted Kremenekcf118d42009-02-04 23:49:09 +0000281 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000282 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000283 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000284
Ted Kremenek78d46242008-07-22 16:21:24 +0000285 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000286 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000287 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000288 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
289 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000290 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000291 report->addRange(E->getSourceRange());
292 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000293 }
294 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000295
Ted Kremenek0c313172009-05-13 19:16:35 +0000296 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000297 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000298 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000299 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000300 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000301};
Ted Kremenek5917d782008-11-21 00:27:44 +0000302
Ted Kremenek78d46242008-07-22 16:21:24 +0000303class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
304public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000305 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000306 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000307
Ted Kremenekcf118d42009-02-04 23:49:09 +0000308 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000309 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
310 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000311
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000312 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000313 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
314 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
315 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000316
Ted Kremenek22bda882008-07-31 20:31:27 +0000317 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000318 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000319
Ted Kremenek22bda882008-07-31 20:31:27 +0000320 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000321 std::string buf;
322 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000323 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000324
Ted Kremenek8aed8062008-10-31 00:13:20 +0000325 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000326 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000327 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000328
Ted Kremenek8aed8062008-10-31 00:13:20 +0000329 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
330 os << "Address of stack memory associated with a compound literal "
331 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000332 << BR.getSourceManager()
333 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000334 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000335
Ted Kremenek8aed8062008-10-31 00:13:20 +0000336 R = CL->getSourceRange();
337 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000338 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
339 const Expr* ARE = AR->getExpr();
340 SourceLocation L = ARE->getLocStart();
341 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000342
Ted Kremenekde8cd192008-11-02 00:35:25 +0000343 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000344 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000345 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000346 }
347 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000348 os << "Address of stack memory associated with local variable '"
349 << V.getRegion()->getString() << "' returned.";
350 }
Mike Stump1eb44332009-09-09 15:08:12 +0000351
Ted Kremenekcf118d42009-02-04 23:49:09 +0000352 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
353 report->addRange(E->getSourceRange());
354 if (R.isValid()) report->addRange(R);
355 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000356 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000357 }
358};
Mike Stump1eb44332009-09-09 15:08:12 +0000359
Ted Kremenek5917d782008-11-21 00:27:44 +0000360class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
361public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000362 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
363 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000364
Ted Kremenekcf118d42009-02-04 23:49:09 +0000365 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000366 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
367 }
Mike Stump1eb44332009-09-09 15:08:12 +0000368
Ted Kremenek0c313172009-05-13 19:16:35 +0000369 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000370 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000371 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000372 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000373 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000374};
Ted Kremenek78d46242008-07-22 16:21:24 +0000375
376class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
377 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000378 GRStateManager& VM;
379 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000380
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000381 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000382
383 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000384 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000385 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000386
Ted Kremenekb7714b22008-07-30 17:49:12 +0000387 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000388 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
389 Expr* E2 = FindExpr(ExI);
390 if (E2) return E2;
391 }
Mike Stump1eb44332009-09-09 15:08:12 +0000392
Ted Kremenek78d46242008-07-22 16:21:24 +0000393 return Ex;
394 }
Mike Stump1eb44332009-09-09 15:08:12 +0000395
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000396 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000397 };
Mike Stump1eb44332009-09-09 15:08:12 +0000398
Ted Kremenek78d46242008-07-22 16:21:24 +0000399public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000400 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000401 : BuiltinBug(eng,"Use of garbage value",
402 "Branch condition evaluates to an undefined or garbage value")
403 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000404
Ted Kremenekcf118d42009-02-04 23:49:09 +0000405 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000406 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
407 E=Eng.undef_branches_end(); I!=E; ++I) {
408
409 // What's going on here: we want to highlight the subexpression of the
410 // condition that is the most likely source of the "uninitialized
411 // branch condition." We do a recursive walk of the condition's
412 // subexpressions and roughly look for the most nested subexpression
413 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000414 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
415 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
416 assert (Ex && "Block must have a terminator.");
417
418 // Get the predecessor node and check if is a PostStmt with the Stmt
419 // being the terminator condition. We want to inspect the state
420 // of that node instead because it will contain main information about
421 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000422 assert (!(*I)->pred_empty());
423
424 // Note: any predecessor will do. They should have identical state,
425 // since all the BlockEdge did was act as an error sink since the value
426 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000427 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000428 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000429 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000430
431 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
432 if (PS->getStmt() == Ex)
433 St = N->getState();
434
435 FindUndefExpr FindIt(Eng.getStateManager(), St);
436 Ex = FindIt.FindExpr(Ex);
437
Ted Kremenek85ac9342009-05-15 05:25:09 +0000438 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000439 R->addRange(Ex->getSourceRange());
440 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000441 }
442 }
Mike Stump1eb44332009-09-09 15:08:12 +0000443
Ted Kremenek85ac9342009-05-15 05:25:09 +0000444 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000445 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000446 BuiltinBugReport *R) {
447 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
448 N);
449 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000450};
451
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000452class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
453public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000454 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000455 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000456 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000457
Ted Kremenekcf118d42009-02-04 23:49:09 +0000458 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000459 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
460 }
461};
Mike Stump1eb44332009-09-09 15:08:12 +0000462
Ted Kremenek159d2482008-12-09 00:44:16 +0000463class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000464public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000465 BadSizeVLA(GRExprEngine* eng) :
466 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000467
Ted Kremenekcf118d42009-02-04 23:49:09 +0000468 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000469 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000470 I = Eng.ExplicitBadSizedVLA.begin(),
471 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
472
473 // Determine whether this was a 'zero-sized' VLA or a VLA with an
474 // undefined size.
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000475 ExplodedNode* N = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000476 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000477 const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
Ted Kremenekefd59942008-12-08 22:47:34 +0000478 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
479 QualType T = Eng.getContext().getCanonicalType(VD->getType());
480 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000481 Expr* SizeExpr = VT->getSizeExpr();
Mike Stump1eb44332009-09-09 15:08:12 +0000482
Ted Kremenek159d2482008-12-09 00:44:16 +0000483 std::string buf;
484 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000485 os << "The expression used to specify the number of elements in the "
486 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000487 << VD->getNameAsString() << "' evaluates to ";
Mike Stump1eb44332009-09-09 15:08:12 +0000488
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000489 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Mike Stump1eb44332009-09-09 15:08:12 +0000490
Ted Kremenekd49967f2009-04-29 21:58:13 +0000491 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000492 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000493 else
494 os << "0. VLAs with no elements have undefined behavior.";
Mike Stump1eb44332009-09-09 15:08:12 +0000495
Ted Kremenekd49967f2009-04-29 21:58:13 +0000496 std::string shortBuf;
497 llvm::raw_string_ostream os_short(shortBuf);
498 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000499 << (isUndefined ? "garbage value for array size"
500 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000501
Ted Kremenek85ac9342009-05-15 05:25:09 +0000502 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
503 os.str().c_str(), N, SizeExpr);
504
Ted Kremenekcf118d42009-02-04 23:49:09 +0000505 report->addRange(SizeExpr->getSourceRange());
506 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000507 }
508 }
Mike Stump1eb44332009-09-09 15:08:12 +0000509
Ted Kremenek85ac9342009-05-15 05:25:09 +0000510 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000511 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000512 BuiltinBugReport *R) {
513 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
514 N);
515 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000516};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000517
Ted Kremenek78d46242008-07-22 16:21:24 +0000518//===----------------------------------------------------------------------===//
519// __attribute__(nonnull) checking
520
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000521class VISIBILITY_HIDDEN CheckAttrNonNull :
522 public CheckerVisitor<CheckAttrNonNull> {
523
Ted Kremenekcf118d42009-02-04 23:49:09 +0000524 BugType *BT;
Mike Stump1eb44332009-09-09 15:08:12 +0000525
Ted Kremenek78d46242008-07-22 16:21:24 +0000526public:
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000527 CheckAttrNonNull() : BT(0) {}
Ted Kremenek31112182009-07-24 00:40:31 +0000528 ~CheckAttrNonNull() {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000529
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000530 static void *getTag() {
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000531 static int x = 0;
532 return &x;
533 }
534
535 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
536 const GRState *state = C.getState();
537 const GRState *originalState = state;
Mike Stump1eb44332009-09-09 15:08:12 +0000538
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000539 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000540 SVal X = state->getSVal(CE->getCallee());
Mike Stump1eb44332009-09-09 15:08:12 +0000541
Zhongxing Xu369f4472009-04-20 05:24:46 +0000542 const FunctionDecl* FD = X.getAsFunctionDecl();
543 if (!FD)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000544 return;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000545
Mike Stump1eb44332009-09-09 15:08:12 +0000546 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000547 if (!Att)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000548 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000549
Ted Kremenek78d46242008-07-22 16:21:24 +0000550 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000551 unsigned idx = 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000552
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000553 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
Ted Kremenek78d46242008-07-22 16:21:24 +0000554 ++I, ++idx) {
Mike Stump1eb44332009-09-09 15:08:12 +0000555
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000556 if (!Att->isNonNull(idx))
557 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000558
Ted Kremenek08780072009-08-24 22:47:34 +0000559 const SVal &V = state->getSVal(*I);
560 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
Mike Stump1eb44332009-09-09 15:08:12 +0000561
Ted Kremenek08780072009-08-24 22:47:34 +0000562 if (!DV)
563 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000564
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000565 ConstraintManager &CM = C.getConstraintManager();
566 const GRState *stateNotNull, *stateNull;
Ted Kremenek08780072009-08-24 22:47:34 +0000567 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000568
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000569 if (stateNull && !stateNotNull) {
570 // Generate an error node. Check for a null node in case
571 // we cache out.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000572 if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000573
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000574 // Lazily allocate the BugType object if it hasn't already been
575 // created. Ownership is transferred to the BugReporter object once
576 // the BugReport is passed to 'EmitWarning'.
577 if (!BT)
578 BT = new BugType("Argument with 'nonnull' attribute passed null",
579 "API");
Mike Stump1eb44332009-09-09 15:08:12 +0000580
Ted Kremenek592362b2009-08-18 01:05:30 +0000581 EnhancedBugReport *R =
582 new EnhancedBugReport(*BT,
583 "Null pointer passed as an argument to a "
584 "'nonnull' parameter", errorNode);
Mike Stump1eb44332009-09-09 15:08:12 +0000585
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000586 // Highlight the range of the argument that was null.
Ted Kremenek592362b2009-08-18 01:05:30 +0000587 const Expr *arg = *I;
588 R->addRange(arg->getSourceRange());
589 R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
Mike Stump1eb44332009-09-09 15:08:12 +0000590
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000591 // Emit the bug report.
592 C.EmitReport(R);
593 }
Mike Stump1eb44332009-09-09 15:08:12 +0000594
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000595 // Always return. Either we cached out or we just emitted an error.
596 return;
597 }
Mike Stump1eb44332009-09-09 15:08:12 +0000598
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000599 // If a pointer value passed the check we should assume that it is
600 // indeed not null from this point forward.
601 assert(stateNotNull);
602 state = stateNotNull;
603 }
Mike Stump1eb44332009-09-09 15:08:12 +0000604
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000605 // If we reach here all of the arguments passed the nonnull check.
606 // If 'state' has been updated generated a new node.
607 if (state != originalState)
Zhongxing Xu6403b572009-09-02 13:26:26 +0000608 C.addTransition(C.GenerateNode(CE, state));
Ted Kremenek78d46242008-07-22 16:21:24 +0000609 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000610};
Ted Kremenek78d46242008-07-22 16:21:24 +0000611
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000612// Undefined arguments checking.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000613
Mike Stump1eb44332009-09-09 15:08:12 +0000614class VISIBILITY_HIDDEN CheckUndefinedArg
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000615 : public CheckerVisitor<CheckUndefinedArg> {
616
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000617 BadArg *BT;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000618
619public:
620 CheckUndefinedArg() : BT(0) {}
621 ~CheckUndefinedArg() {}
622
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000623 static void *getTag() {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000624 static int x = 0;
625 return &x;
626 }
627
628 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
629};
630
631void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
632 for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
633 I != E; ++I) {
634 if (C.getState()->getSVal(*I).isUndef()) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000635 if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000636 if (!BT)
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000637 BT = new BadArg();
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000638 // Generate a report for this bug.
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000639 ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000640 ErrorNode, *I);
641 Report->addRange((*I)->getSourceRange());
642 C.EmitReport(Report);
643 }
644 }
645 }
646}
647
Zhongxing Xud99f3612009-09-02 08:10:35 +0000648class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
649 BadCall *BT;
650
651public:
652 CheckBadCall() : BT(0) {}
653 ~CheckBadCall() {}
654
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000655 static void *getTag() {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000656 static int x = 0;
657 return &x;
658 }
659
660 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
661};
662
663void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
664 const Expr *Callee = CE->getCallee()->IgnoreParens();
665 SVal L = C.getState()->getSVal(Callee);
666
667 if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000668 if (ExplodedNode *N = C.GenerateNode(CE, true)) {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000669 if (!BT)
670 BT = new BadCall();
671 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
672 }
673 }
674}
675
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000676} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000677
Ted Kremenek78d46242008-07-22 16:21:24 +0000678//===----------------------------------------------------------------------===//
679// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000680//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000681
682void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000683 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
684 // are different than what probably many checks will do since they don't
685 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
686 // analyzing a function. Generation of BugReport objects is done via a call
687 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000688 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000689 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000690 BR.Register(new RetStack(this));
691 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000692 BR.Register(new BadMsgExprArg(this));
693 BR.Register(new BadReceiver(this));
694 BR.Register(new OutOfBoundMemoryAccess(this));
695 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000696 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000697 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000698
Ted Kremenekcf118d42009-02-04 23:49:09 +0000699 // The following checks do not need to have their associated BugTypes
700 // explicitly registered with the BugReporter. If they issue any BugReports,
701 // their associated BugType will get registered with the BugReporter
702 // automatically. Note that the check itself is owned by the GRExprEngine
703 // object.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000704 registerCheck<CheckAttrNonNull>(new CheckAttrNonNull());
705 registerCheck<CheckUndefinedArg>(new CheckUndefinedArg());
706 registerCheck<CheckBadCall>(new CheckBadCall());
Zhongxing Xu9e56d232009-10-31 10:02:37 +0000707 registerCheck<DivZeroChecker>(new DivZeroChecker());
Zhongxing Xu246a9ad2009-10-31 08:44:33 +0000708 registerCheck<UndefDerefChecker>(new UndefDerefChecker());
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000709 registerCheck<NullDerefChecker>(new NullDerefChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000710}