blob: bfaf0f03795cb7fd321afdb218de844404fb3dc2 [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"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000020#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000021#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000022#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000023#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000024
25using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000026using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000027
28//===----------------------------------------------------------------------===//
29// Utility functions.
30//===----------------------------------------------------------------------===//
31
32template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000033ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000034 return *I;
35}
36
37template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000038ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000039 return I->first;
40}
41
42//===----------------------------------------------------------------------===//
43// Bug Descriptions.
44//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000045namespace clang {
46class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000047public:
48 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000049 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000050 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000051
Ted Kremenek85ac9342009-05-15 05:25:09 +000052 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000053 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000054 : RangedBugReport(bt, shortDesc, desc, n) {}
55
Ted Kremenekdd986cc2009-05-07 00:45:33 +000056 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000057 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000058};
59
Zhongxing Xuec9227f2009-10-29 02:09:30 +000060void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
61 const ExplodedNode* N) {
62 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
63}
Mike Stump1eb44332009-09-09 15:08:12 +000064
Ted Kremenekdd986cc2009-05-07 00:45:33 +000065template <typename ITER>
66void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
67 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
68 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000069}
Mike Stump1eb44332009-09-09 15:08:12 +000070
Ted Kremenek0c313172009-05-13 19:16:35 +000071class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000072public:
73 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000074 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000075
Ted Kremenek0c313172009-05-13 19:16:35 +000076 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000077 for (GRExprEngine::nil_receiver_struct_ret_iterator
78 I=Eng.nil_receiver_struct_ret_begin(),
79 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
80
81 std::string sbuf;
82 llvm::raw_string_ostream os(sbuf);
83 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000084 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000085 os << "The receiver in the message expression is 'nil' and results in the"
86 " returned value (of type '"
87 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000088 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000089
Ted Kremenek0c313172009-05-13 19:16:35 +000090 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000091 R->addRange(ME->getReceiver()->getSourceRange());
92 BR.EmitReport(R);
93 }
94 }
Mike Stump1eb44332009-09-09 15:08:12 +000095
Ted Kremenek0c313172009-05-13 19:16:35 +000096 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000097 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +000098 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +000099 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000100 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000101};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000102
Ted Kremenek0c313172009-05-13 19:16:35 +0000103class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000104public:
105 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000106 BuiltinBug(eng,
107 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000108
Ted Kremenek0c313172009-05-13 19:16:35 +0000109 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000110 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
111 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
112 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000113
Ted Kremenek899b3de2009-04-08 03:07:17 +0000114 std::string sbuf;
115 llvm::raw_string_ostream os(sbuf);
116 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000117 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000118 os << "The receiver in the message expression is 'nil' and results in the"
119 " returned value (of type '"
120 << ME->getType().getAsString()
121 << "' and of size "
122 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000123 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000124
Ted Kremenek0c313172009-05-13 19:16:35 +0000125 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000126 R->addRange(ME->getReceiver()->getSourceRange());
127 BR.EmitReport(R);
128 }
Mike Stump1eb44332009-09-09 15:08:12 +0000129 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000130 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000131 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000132 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000133 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000134 }
135};
Mike Stump1eb44332009-09-09 15:08:12 +0000136
Ted Kremenek78d46242008-07-22 16:21:24 +0000137class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
138public:
Zhongxing Xu6403b572009-09-02 13:26:26 +0000139 DivZero(GRExprEngine* eng = 0)
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000140 : BuiltinBug(eng,"Division by zero") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000141
Ted Kremenek85ac9342009-05-15 05:25:09 +0000142 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000143 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000144 BuiltinBugReport *R) {
145 registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
146 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000147};
Mike Stump1eb44332009-09-09 15:08:12 +0000148
Ted Kremenek78d46242008-07-22 16:21:24 +0000149class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
150public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000151 UndefResult(GRExprEngine* eng)
152 : BuiltinBug(eng,"Undefined or garbage result",
153 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000154
Ted Kremenekcf118d42009-02-04 23:49:09 +0000155 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000156 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
157 E = Eng.undef_results_end(); I!=E; ++I) {
158
159 ExplodedNode *N = *I;
160 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
161 BuiltinBugReport *report = NULL;
162
163 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
164 llvm::SmallString<256> sbuf;
165 llvm::raw_svector_ostream OS(sbuf);
166 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000167 const Expr *Ex = NULL;
168 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000169
170 if (ST->getSVal(B->getLHS()).isUndef()) {
171 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000172 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000173 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000174 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000175 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000176 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000177 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000178
179 if (Ex) {
180 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000181 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000182 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000183 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000184 }
185 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000186 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000187 OS << "The result of the '"
188 << BinaryOperator::getOpcodeStr(B->getOpcode())
189 << "' expression is undefined";
190 }
191
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000192 // FIXME: Use StringRefs to pass string information.
193 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000194 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000195 }
196 else {
197 report = new BuiltinBugReport(*this,
198 "Expression evaluates to an uninitialized"
199 " or undefined value", N);
200 }
201
202 BR.EmitReport(report);
203 }
204 }
205
206 void registerInitialVisitors(BugReporterContext& BRC,
207 const ExplodedNode* N,
208 BuiltinBugReport *R) {
209
210 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
211 const Stmt *X = S;
212
213 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
214 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000215 if (ST->getSVal(B->getLHS()).isUndef())
216 X = B->getLHS();
217 else if (ST->getSVal(B->getRHS()).isUndef())
218 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000219 }
220
221 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000222 }
223};
Mike Stump1eb44332009-09-09 15:08:12 +0000224
Ted Kremenek78d46242008-07-22 16:21:24 +0000225class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
226public:
Zhongxing Xud99f3612009-09-02 08:10:35 +0000227 BadCall(GRExprEngine *eng = 0)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000228 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000229 "Called function pointer is a null or undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000230
Ted Kremenek85ac9342009-05-15 05:25:09 +0000231 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000232 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000233 BuiltinBugReport *R) {
234 registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
235 }
236};
237
238
239class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
240 const Stmt *Arg;
241public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000242 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000243 const Stmt *arg)
244 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000245
Ted Kremenek85ac9342009-05-15 05:25:09 +0000246 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000247 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000248 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
249
250 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000251};
252
253class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000254public:
255 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000256 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000257
Ted Kremenekcf118d42009-02-04 23:49:09 +0000258 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000259 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000260
Ted Kremenek85ac9342009-05-15 05:25:09 +0000261 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000262 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000263 BuiltinBugReport *R) {
264 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
265 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000266 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000267};
Mike Stump1eb44332009-09-09 15:08:12 +0000268
Ted Kremenek78d46242008-07-22 16:21:24 +0000269class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
270public:
Mike Stump1eb44332009-09-09 15:08:12 +0000271 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000272 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000273
Ted Kremenekcf118d42009-02-04 23:49:09 +0000274 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000275 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000276 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000277 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000278 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
279 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000280 report->addRange(I->second->getSourceRange());
281 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000282 }
283 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000284};
Mike Stump1eb44332009-09-09 15:08:12 +0000285
Ted Kremenek78d46242008-07-22 16:21:24 +0000286class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000287public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000288 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000289 : BuiltinBug(eng,"Uninitialized receiver",
290 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000291
Ted Kremenekcf118d42009-02-04 23:49:09 +0000292 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000293 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000294 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000295
Ted Kremenek78d46242008-07-22 16:21:24 +0000296 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000297 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000298 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000299 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
300 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000301 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000302 report->addRange(E->getSourceRange());
303 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000304 }
305 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000306
Ted Kremenek0c313172009-05-13 19:16:35 +0000307 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000308 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000309 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000310 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000311 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000312};
Ted Kremenek5917d782008-11-21 00:27:44 +0000313
Ted Kremenek78d46242008-07-22 16:21:24 +0000314class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
315public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000316 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000317 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000318
Ted Kremenekcf118d42009-02-04 23:49:09 +0000319 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000320 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
321 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000322
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000323 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000324 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
325 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
326 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000327
Ted Kremenek22bda882008-07-31 20:31:27 +0000328 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000329 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000330
Ted Kremenek22bda882008-07-31 20:31:27 +0000331 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000332 std::string buf;
333 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000334 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000335
Ted Kremenek8aed8062008-10-31 00:13:20 +0000336 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000337 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000338 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000339
Ted Kremenek8aed8062008-10-31 00:13:20 +0000340 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
341 os << "Address of stack memory associated with a compound literal "
342 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000343 << BR.getSourceManager()
344 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000345 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000346
Ted Kremenek8aed8062008-10-31 00:13:20 +0000347 R = CL->getSourceRange();
348 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000349 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
350 const Expr* ARE = AR->getExpr();
351 SourceLocation L = ARE->getLocStart();
352 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000353
Ted Kremenekde8cd192008-11-02 00:35:25 +0000354 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000355 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000356 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000357 }
358 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000359 os << "Address of stack memory associated with local variable '"
360 << V.getRegion()->getString() << "' returned.";
361 }
Mike Stump1eb44332009-09-09 15:08:12 +0000362
Ted Kremenekcf118d42009-02-04 23:49:09 +0000363 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
364 report->addRange(E->getSourceRange());
365 if (R.isValid()) report->addRange(R);
366 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000367 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000368 }
369};
Mike Stump1eb44332009-09-09 15:08:12 +0000370
Ted Kremenek5917d782008-11-21 00:27:44 +0000371class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
372public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000373 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
374 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000375
Ted Kremenekcf118d42009-02-04 23:49:09 +0000376 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000377 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
378 }
Mike Stump1eb44332009-09-09 15:08:12 +0000379
Ted Kremenek0c313172009-05-13 19:16:35 +0000380 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000381 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000382 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000383 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000384 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000385};
Ted Kremenek78d46242008-07-22 16:21:24 +0000386
387class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
388 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000389 GRStateManager& VM;
390 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000391
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000392 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000393
394 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000395 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000396 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000397
Ted Kremenekb7714b22008-07-30 17:49:12 +0000398 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000399 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
400 Expr* E2 = FindExpr(ExI);
401 if (E2) return E2;
402 }
Mike Stump1eb44332009-09-09 15:08:12 +0000403
Ted Kremenek78d46242008-07-22 16:21:24 +0000404 return Ex;
405 }
Mike Stump1eb44332009-09-09 15:08:12 +0000406
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000407 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000408 };
Mike Stump1eb44332009-09-09 15:08:12 +0000409
Ted Kremenek78d46242008-07-22 16:21:24 +0000410public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000411 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000412 : BuiltinBug(eng,"Use of garbage value",
413 "Branch condition evaluates to an undefined or garbage value")
414 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000415
Ted Kremenekcf118d42009-02-04 23:49:09 +0000416 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000417 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
418 E=Eng.undef_branches_end(); I!=E; ++I) {
419
420 // What's going on here: we want to highlight the subexpression of the
421 // condition that is the most likely source of the "uninitialized
422 // branch condition." We do a recursive walk of the condition's
423 // subexpressions and roughly look for the most nested subexpression
424 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000425 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
426 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
427 assert (Ex && "Block must have a terminator.");
428
429 // Get the predecessor node and check if is a PostStmt with the Stmt
430 // being the terminator condition. We want to inspect the state
431 // of that node instead because it will contain main information about
432 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000433 assert (!(*I)->pred_empty());
434
435 // Note: any predecessor will do. They should have identical state,
436 // since all the BlockEdge did was act as an error sink since the value
437 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000438 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000439 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000440 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000441
442 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
443 if (PS->getStmt() == Ex)
444 St = N->getState();
445
446 FindUndefExpr FindIt(Eng.getStateManager(), St);
447 Ex = FindIt.FindExpr(Ex);
448
Ted Kremenek85ac9342009-05-15 05:25:09 +0000449 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000450 R->addRange(Ex->getSourceRange());
451 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000452 }
453 }
Mike Stump1eb44332009-09-09 15:08:12 +0000454
Ted Kremenek85ac9342009-05-15 05:25:09 +0000455 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000456 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000457 BuiltinBugReport *R) {
458 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
459 N);
460 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000461};
462
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000463class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
464public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000465 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000466 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000467 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000468
Ted Kremenekcf118d42009-02-04 23:49:09 +0000469 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000470 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
471 }
472};
Mike Stump1eb44332009-09-09 15:08:12 +0000473
Ted Kremenek159d2482008-12-09 00:44:16 +0000474class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000475public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000476 BadSizeVLA(GRExprEngine* eng) :
477 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000478
Ted Kremenekcf118d42009-02-04 23:49:09 +0000479 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000480 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000481 I = Eng.ExplicitBadSizedVLA.begin(),
482 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
483
484 // Determine whether this was a 'zero-sized' VLA or a VLA with an
485 // undefined size.
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000486 ExplodedNode* N = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000487 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000488 const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
Ted Kremenekefd59942008-12-08 22:47:34 +0000489 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
490 QualType T = Eng.getContext().getCanonicalType(VD->getType());
491 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000492 Expr* SizeExpr = VT->getSizeExpr();
Mike Stump1eb44332009-09-09 15:08:12 +0000493
Ted Kremenek159d2482008-12-09 00:44:16 +0000494 std::string buf;
495 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000496 os << "The expression used to specify the number of elements in the "
497 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000498 << VD->getNameAsString() << "' evaluates to ";
Mike Stump1eb44332009-09-09 15:08:12 +0000499
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000500 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Mike Stump1eb44332009-09-09 15:08:12 +0000501
Ted Kremenekd49967f2009-04-29 21:58:13 +0000502 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000503 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000504 else
505 os << "0. VLAs with no elements have undefined behavior.";
Mike Stump1eb44332009-09-09 15:08:12 +0000506
Ted Kremenekd49967f2009-04-29 21:58:13 +0000507 std::string shortBuf;
508 llvm::raw_string_ostream os_short(shortBuf);
509 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000510 << (isUndefined ? "garbage value for array size"
511 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000512
Ted Kremenek85ac9342009-05-15 05:25:09 +0000513 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
514 os.str().c_str(), N, SizeExpr);
515
Ted Kremenekcf118d42009-02-04 23:49:09 +0000516 report->addRange(SizeExpr->getSourceRange());
517 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000518 }
519 }
Mike Stump1eb44332009-09-09 15:08:12 +0000520
Ted Kremenek85ac9342009-05-15 05:25:09 +0000521 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000522 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000523 BuiltinBugReport *R) {
524 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
525 N);
526 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000527};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000528
Ted Kremenek78d46242008-07-22 16:21:24 +0000529//===----------------------------------------------------------------------===//
530// __attribute__(nonnull) checking
531
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000532class VISIBILITY_HIDDEN CheckAttrNonNull :
533 public CheckerVisitor<CheckAttrNonNull> {
534
Ted Kremenekcf118d42009-02-04 23:49:09 +0000535 BugType *BT;
Mike Stump1eb44332009-09-09 15:08:12 +0000536
Ted Kremenek78d46242008-07-22 16:21:24 +0000537public:
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000538 CheckAttrNonNull() : BT(0) {}
Ted Kremenek31112182009-07-24 00:40:31 +0000539 ~CheckAttrNonNull() {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000540
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000541 static void *getTag() {
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000542 static int x = 0;
543 return &x;
544 }
545
546 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
547 const GRState *state = C.getState();
548 const GRState *originalState = state;
Mike Stump1eb44332009-09-09 15:08:12 +0000549
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000550 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000551 SVal X = state->getSVal(CE->getCallee());
Mike Stump1eb44332009-09-09 15:08:12 +0000552
Zhongxing Xu369f4472009-04-20 05:24:46 +0000553 const FunctionDecl* FD = X.getAsFunctionDecl();
554 if (!FD)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000555 return;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000556
Mike Stump1eb44332009-09-09 15:08:12 +0000557 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000558 if (!Att)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000559 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000560
Ted Kremenek78d46242008-07-22 16:21:24 +0000561 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000562 unsigned idx = 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000563
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000564 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
Ted Kremenek78d46242008-07-22 16:21:24 +0000565 ++I, ++idx) {
Mike Stump1eb44332009-09-09 15:08:12 +0000566
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000567 if (!Att->isNonNull(idx))
568 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000569
Ted Kremenek08780072009-08-24 22:47:34 +0000570 const SVal &V = state->getSVal(*I);
571 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
Mike Stump1eb44332009-09-09 15:08:12 +0000572
Ted Kremenek08780072009-08-24 22:47:34 +0000573 if (!DV)
574 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000575
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000576 ConstraintManager &CM = C.getConstraintManager();
577 const GRState *stateNotNull, *stateNull;
Ted Kremenek08780072009-08-24 22:47:34 +0000578 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000579
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000580 if (stateNull && !stateNotNull) {
581 // Generate an error node. Check for a null node in case
582 // we cache out.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000583 if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000584
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000585 // Lazily allocate the BugType object if it hasn't already been
586 // created. Ownership is transferred to the BugReporter object once
587 // the BugReport is passed to 'EmitWarning'.
588 if (!BT)
589 BT = new BugType("Argument with 'nonnull' attribute passed null",
590 "API");
Mike Stump1eb44332009-09-09 15:08:12 +0000591
Ted Kremenek592362b2009-08-18 01:05:30 +0000592 EnhancedBugReport *R =
593 new EnhancedBugReport(*BT,
594 "Null pointer passed as an argument to a "
595 "'nonnull' parameter", errorNode);
Mike Stump1eb44332009-09-09 15:08:12 +0000596
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000597 // Highlight the range of the argument that was null.
Ted Kremenek592362b2009-08-18 01:05:30 +0000598 const Expr *arg = *I;
599 R->addRange(arg->getSourceRange());
600 R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
Mike Stump1eb44332009-09-09 15:08:12 +0000601
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000602 // Emit the bug report.
603 C.EmitReport(R);
604 }
Mike Stump1eb44332009-09-09 15:08:12 +0000605
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000606 // Always return. Either we cached out or we just emitted an error.
607 return;
608 }
Mike Stump1eb44332009-09-09 15:08:12 +0000609
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000610 // If a pointer value passed the check we should assume that it is
611 // indeed not null from this point forward.
612 assert(stateNotNull);
613 state = stateNotNull;
614 }
Mike Stump1eb44332009-09-09 15:08:12 +0000615
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000616 // If we reach here all of the arguments passed the nonnull check.
617 // If 'state' has been updated generated a new node.
618 if (state != originalState)
Zhongxing Xu6403b572009-09-02 13:26:26 +0000619 C.addTransition(C.GenerateNode(CE, state));
Ted Kremenek78d46242008-07-22 16:21:24 +0000620 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000621};
Ted Kremenek78d46242008-07-22 16:21:24 +0000622
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000623// Undefined arguments checking.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000624
Mike Stump1eb44332009-09-09 15:08:12 +0000625class VISIBILITY_HIDDEN CheckUndefinedArg
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000626 : public CheckerVisitor<CheckUndefinedArg> {
627
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000628 BadArg *BT;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000629
630public:
631 CheckUndefinedArg() : BT(0) {}
632 ~CheckUndefinedArg() {}
633
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000634 static void *getTag() {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000635 static int x = 0;
636 return &x;
637 }
638
639 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
640};
641
642void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
643 for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
644 I != E; ++I) {
645 if (C.getState()->getSVal(*I).isUndef()) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000646 if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000647 if (!BT)
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000648 BT = new BadArg();
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000649 // Generate a report for this bug.
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000650 ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000651 ErrorNode, *I);
652 Report->addRange((*I)->getSourceRange());
653 C.EmitReport(Report);
654 }
655 }
656 }
657}
658
Zhongxing Xud99f3612009-09-02 08:10:35 +0000659class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
660 BadCall *BT;
661
662public:
663 CheckBadCall() : BT(0) {}
664 ~CheckBadCall() {}
665
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000666 static void *getTag() {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000667 static int x = 0;
668 return &x;
669 }
670
671 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
672};
673
674void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
675 const Expr *Callee = CE->getCallee()->IgnoreParens();
676 SVal L = C.getState()->getSVal(Callee);
677
678 if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000679 if (ExplodedNode *N = C.GenerateNode(CE, true)) {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000680 if (!BT)
681 BT = new BadCall();
682 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
683 }
684 }
685}
686
Zhongxing Xu524e4652009-10-22 01:58:10 +0000687class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000688 DivZero *BT;
689public:
Zhongxing Xu524e4652009-10-22 01:58:10 +0000690 CheckDivZero() : BT(0) {}
691 ~CheckDivZero() {}
Zhongxing Xu6403b572009-09-02 13:26:26 +0000692
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000693 static void *getTag() {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000694 static int x;
695 return &x;
696 }
697
698 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
699};
700
Zhongxing Xu524e4652009-10-22 01:58:10 +0000701void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
702 const BinaryOperator *B) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000703 BinaryOperator::Opcode Op = B->getOpcode();
704 if (Op != BinaryOperator::Div &&
705 Op != BinaryOperator::Rem &&
706 Op != BinaryOperator::DivAssign &&
707 Op != BinaryOperator::RemAssign)
708 return;
709
710 if (!B->getRHS()->getType()->isIntegerType() ||
711 !B->getRHS()->getType()->isScalarType())
712 return;
713
Zhongxing Xu6403b572009-09-02 13:26:26 +0000714 SVal Denom = C.getState()->getSVal(B->getRHS());
Ted Kremenek970e03a2009-09-03 01:48:03 +0000715 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
716
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000717 // Divide-by-undefined handled in the generic checking for uses of
718 // undefined values.
Mike Stump1eb44332009-09-09 15:08:12 +0000719 if (!DV)
Ted Kremenek970e03a2009-09-03 01:48:03 +0000720 return;
721
Zhongxing Xu6403b572009-09-02 13:26:26 +0000722 // Check for divide by zero.
723 ConstraintManager &CM = C.getConstraintManager();
724 const GRState *stateNotZero, *stateZero;
Ted Kremenek970e03a2009-09-03 01:48:03 +0000725 llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000726
Zhongxing Xu6403b572009-09-02 13:26:26 +0000727 if (stateZero && !stateNotZero) {
728 if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
729 if (!BT)
730 BT = new DivZero();
Mike Stump1eb44332009-09-09 15:08:12 +0000731
Zhongxing Xu6403b572009-09-02 13:26:26 +0000732 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
733 }
734 return;
735 }
736
Zhongxing Xu524e4652009-10-22 01:58:10 +0000737 // If we get here, then the denom should not be zero. We abandon the implicit
738 // zero denom case for now.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000739 if (stateNotZero != C.getState())
740 C.addTransition(C.GenerateNode(B, stateNotZero));
741}
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000742
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000743
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000744} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000745
Ted Kremenek78d46242008-07-22 16:21:24 +0000746//===----------------------------------------------------------------------===//
747// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000748//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000749
750void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000751 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
752 // are different than what probably many checks will do since they don't
753 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
754 // analyzing a function. Generation of BugReport objects is done via a call
755 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000756 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000757 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000758 BR.Register(new RetStack(this));
759 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000760 BR.Register(new BadMsgExprArg(this));
761 BR.Register(new BadReceiver(this));
762 BR.Register(new OutOfBoundMemoryAccess(this));
763 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000764 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000765 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000766
Ted Kremenekcf118d42009-02-04 23:49:09 +0000767 // The following checks do not need to have their associated BugTypes
768 // explicitly registered with the BugReporter. If they issue any BugReports,
769 // their associated BugType will get registered with the BugReporter
770 // automatically. Note that the check itself is owned by the GRExprEngine
771 // object.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000772 registerCheck<CheckAttrNonNull>(new CheckAttrNonNull());
773 registerCheck<CheckUndefinedArg>(new CheckUndefinedArg());
774 registerCheck<CheckBadCall>(new CheckBadCall());
775 registerCheck<CheckDivZero>(new CheckDivZero());
Zhongxing Xu246a9ad2009-10-31 08:44:33 +0000776 registerCheck<UndefDerefChecker>(new UndefDerefChecker());
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000777 registerCheck<NullDerefChecker>(new NullDerefChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000778}