blob: 089d25d6cf5be2167cc3a2f963718fcfef0afb7a [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"
Zhongxing Xu8958fff2009-11-03 06:46:03 +000022#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
Zhongxing Xu94943b62009-11-03 07:35:33 +000023#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
Zhongxing Xu5206f0b2009-11-03 12:13:38 +000024#include "clang/Analysis/PathSensitive/Checkers/UndefSizedVLAChecker.h"
25#include "clang/Analysis/PathSensitive/Checkers/ZeroSizedVLAChecker.h"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000026#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000027#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000028#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000029#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000030
31using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000032using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000033
34//===----------------------------------------------------------------------===//
35// Utility functions.
36//===----------------------------------------------------------------------===//
37
38template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000039ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000040 return *I;
41}
42
43template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000044ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000045 return I->first;
46}
47
48//===----------------------------------------------------------------------===//
49// Bug Descriptions.
50//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000051namespace clang {
52class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000053public:
54 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000055 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000056 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000057
Ted Kremenek85ac9342009-05-15 05:25:09 +000058 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000059 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000060 : RangedBugReport(bt, shortDesc, desc, n) {}
61
Ted Kremenekdd986cc2009-05-07 00:45:33 +000062 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000063 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000064};
65
Zhongxing Xuec9227f2009-10-29 02:09:30 +000066void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
67 const ExplodedNode* N) {
68 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
69}
Mike Stump1eb44332009-09-09 15:08:12 +000070
Ted Kremenekdd986cc2009-05-07 00:45:33 +000071template <typename ITER>
72void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
73 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
74 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000075}
Mike Stump1eb44332009-09-09 15:08:12 +000076
Ted Kremenek0c313172009-05-13 19:16:35 +000077class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000078public:
79 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000080 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000081
Ted Kremenek0c313172009-05-13 19:16:35 +000082 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000083 for (GRExprEngine::nil_receiver_struct_ret_iterator
84 I=Eng.nil_receiver_struct_ret_begin(),
85 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
86
87 std::string sbuf;
88 llvm::raw_string_ostream os(sbuf);
89 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000090 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000091 os << "The receiver in the message expression is 'nil' and results in the"
92 " returned value (of type '"
93 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000094 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000095
Ted Kremenek0c313172009-05-13 19:16:35 +000096 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000097 R->addRange(ME->getReceiver()->getSourceRange());
98 BR.EmitReport(R);
99 }
100 }
Mike Stump1eb44332009-09-09 15:08:12 +0000101
Ted Kremenek0c313172009-05-13 19:16:35 +0000102 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000103 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000104 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000105 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000106 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000107};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000108
Ted Kremenek0c313172009-05-13 19:16:35 +0000109class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000110public:
111 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000112 BuiltinBug(eng,
113 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000114
Ted Kremenek0c313172009-05-13 19:16:35 +0000115 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000116 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
117 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
118 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000119
Ted Kremenek899b3de2009-04-08 03:07:17 +0000120 std::string sbuf;
121 llvm::raw_string_ostream os(sbuf);
122 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000123 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000124 os << "The receiver in the message expression is 'nil' and results in the"
125 " returned value (of type '"
126 << ME->getType().getAsString()
127 << "' and of size "
128 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000129 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000130
Ted Kremenek0c313172009-05-13 19:16:35 +0000131 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000132 R->addRange(ME->getReceiver()->getSourceRange());
133 BR.EmitReport(R);
134 }
Mike Stump1eb44332009-09-09 15:08:12 +0000135 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000136 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000137 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000138 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000139 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000140 }
141};
Mike Stump1eb44332009-09-09 15:08:12 +0000142
Ted Kremenek78d46242008-07-22 16:21:24 +0000143class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
144public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000145 UndefResult(GRExprEngine* eng)
146 : BuiltinBug(eng,"Undefined or garbage result",
147 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000148
Ted Kremenekcf118d42009-02-04 23:49:09 +0000149 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000150 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
151 E = Eng.undef_results_end(); I!=E; ++I) {
152
153 ExplodedNode *N = *I;
154 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
155 BuiltinBugReport *report = NULL;
156
157 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
158 llvm::SmallString<256> sbuf;
159 llvm::raw_svector_ostream OS(sbuf);
160 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000161 const Expr *Ex = NULL;
162 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000163
164 if (ST->getSVal(B->getLHS()).isUndef()) {
165 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000166 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000167 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000168 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000169 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000170 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000171 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000172
173 if (Ex) {
174 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000175 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000176 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000177 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000178 }
179 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000180 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000181 OS << "The result of the '"
182 << BinaryOperator::getOpcodeStr(B->getOpcode())
183 << "' expression is undefined";
184 }
185
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000186 // FIXME: Use StringRefs to pass string information.
187 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000188 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000189 }
190 else {
191 report = new BuiltinBugReport(*this,
192 "Expression evaluates to an uninitialized"
193 " or undefined value", N);
194 }
195
196 BR.EmitReport(report);
197 }
198 }
199
200 void registerInitialVisitors(BugReporterContext& BRC,
201 const ExplodedNode* N,
202 BuiltinBugReport *R) {
203
204 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
205 const Stmt *X = S;
206
207 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
208 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000209 if (ST->getSVal(B->getLHS()).isUndef())
210 X = B->getLHS();
211 else if (ST->getSVal(B->getRHS()).isUndef())
212 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000213 }
214
215 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000216 }
217};
Mike Stump1eb44332009-09-09 15:08:12 +0000218
Ted Kremenek85ac9342009-05-15 05:25:09 +0000219class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
220 const Stmt *Arg;
221public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000222 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000223 const Stmt *arg)
224 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000225
Ted Kremenek85ac9342009-05-15 05:25:09 +0000226 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000227 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000228 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
229
230 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000231};
232
233class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000234public:
235 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000236 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000237
Ted Kremenekcf118d42009-02-04 23:49:09 +0000238 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000239 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000240
Ted Kremenek85ac9342009-05-15 05:25:09 +0000241 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000242 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000243 BuiltinBugReport *R) {
244 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
245 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000246 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000247};
Mike Stump1eb44332009-09-09 15:08:12 +0000248
Ted Kremenek78d46242008-07-22 16:21:24 +0000249class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
250public:
Mike Stump1eb44332009-09-09 15:08:12 +0000251 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000252 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000253
Ted Kremenekcf118d42009-02-04 23:49:09 +0000254 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000255 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000256 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000257 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000258 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
259 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000260 report->addRange(I->second->getSourceRange());
261 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000262 }
263 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000264};
Mike Stump1eb44332009-09-09 15:08:12 +0000265
Ted Kremenek78d46242008-07-22 16:21:24 +0000266class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000267public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000268 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000269 : BuiltinBug(eng,"Uninitialized receiver",
270 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000271
Ted Kremenekcf118d42009-02-04 23:49:09 +0000272 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000273 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000274 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000275
Ted Kremenek78d46242008-07-22 16:21:24 +0000276 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000277 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000278 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000279 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
280 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000281 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000282 report->addRange(E->getSourceRange());
283 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000284 }
285 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000286
Ted Kremenek0c313172009-05-13 19:16:35 +0000287 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000288 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000289 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000290 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000291 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000292};
Ted Kremenek5917d782008-11-21 00:27:44 +0000293
Ted Kremenek78d46242008-07-22 16:21:24 +0000294class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
295public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000296 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000297 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000298
Ted Kremenekcf118d42009-02-04 23:49:09 +0000299 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000300 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
301 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000302
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000303 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000304 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
305 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
306 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000307
Ted Kremenek22bda882008-07-31 20:31:27 +0000308 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000309 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000310
Ted Kremenek22bda882008-07-31 20:31:27 +0000311 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000312 std::string buf;
313 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000314 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000315
Ted Kremenek8aed8062008-10-31 00:13:20 +0000316 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000317 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000318 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000319
Ted Kremenek8aed8062008-10-31 00:13:20 +0000320 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
321 os << "Address of stack memory associated with a compound literal "
322 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000323 << BR.getSourceManager()
324 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000325 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000326
Ted Kremenek8aed8062008-10-31 00:13:20 +0000327 R = CL->getSourceRange();
328 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000329 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
330 const Expr* ARE = AR->getExpr();
331 SourceLocation L = ARE->getLocStart();
332 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000333
Ted Kremenekde8cd192008-11-02 00:35:25 +0000334 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000335 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000336 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000337 }
338 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000339 os << "Address of stack memory associated with local variable '"
340 << V.getRegion()->getString() << "' returned.";
341 }
Mike Stump1eb44332009-09-09 15:08:12 +0000342
Ted Kremenekcf118d42009-02-04 23:49:09 +0000343 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
344 report->addRange(E->getSourceRange());
345 if (R.isValid()) report->addRange(R);
346 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000347 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000348 }
349};
Mike Stump1eb44332009-09-09 15:08:12 +0000350
Ted Kremenek5917d782008-11-21 00:27:44 +0000351class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
352public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000353 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
354 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000355
Ted Kremenekcf118d42009-02-04 23:49:09 +0000356 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000357 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
358 }
Mike Stump1eb44332009-09-09 15:08:12 +0000359
Ted Kremenek0c313172009-05-13 19:16:35 +0000360 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000361 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000362 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000363 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000364 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000365};
Ted Kremenek78d46242008-07-22 16:21:24 +0000366
367class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
368 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000369 GRStateManager& VM;
370 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000371
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000372 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000373
374 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000375 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000376 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000377
Ted Kremenekb7714b22008-07-30 17:49:12 +0000378 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000379 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
380 Expr* E2 = FindExpr(ExI);
381 if (E2) return E2;
382 }
Mike Stump1eb44332009-09-09 15:08:12 +0000383
Ted Kremenek78d46242008-07-22 16:21:24 +0000384 return Ex;
385 }
Mike Stump1eb44332009-09-09 15:08:12 +0000386
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000387 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000388 };
Mike Stump1eb44332009-09-09 15:08:12 +0000389
Ted Kremenek78d46242008-07-22 16:21:24 +0000390public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000391 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000392 : BuiltinBug(eng,"Use of garbage value",
393 "Branch condition evaluates to an undefined or garbage value")
394 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000395
Ted Kremenekcf118d42009-02-04 23:49:09 +0000396 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000397 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
398 E=Eng.undef_branches_end(); I!=E; ++I) {
399
400 // What's going on here: we want to highlight the subexpression of the
401 // condition that is the most likely source of the "uninitialized
402 // branch condition." We do a recursive walk of the condition's
403 // subexpressions and roughly look for the most nested subexpression
404 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000405 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
406 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
407 assert (Ex && "Block must have a terminator.");
408
409 // Get the predecessor node and check if is a PostStmt with the Stmt
410 // being the terminator condition. We want to inspect the state
411 // of that node instead because it will contain main information about
412 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000413 assert (!(*I)->pred_empty());
414
415 // Note: any predecessor will do. They should have identical state,
416 // since all the BlockEdge did was act as an error sink since the value
417 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000418 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000419 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000420 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000421
422 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
423 if (PS->getStmt() == Ex)
424 St = N->getState();
425
426 FindUndefExpr FindIt(Eng.getStateManager(), St);
427 Ex = FindIt.FindExpr(Ex);
428
Ted Kremenek85ac9342009-05-15 05:25:09 +0000429 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000430 R->addRange(Ex->getSourceRange());
431 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000432 }
433 }
Mike Stump1eb44332009-09-09 15:08:12 +0000434
Ted Kremenek85ac9342009-05-15 05:25:09 +0000435 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000436 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000437 BuiltinBugReport *R) {
438 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
439 N);
440 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000441};
442
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000443class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
444public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000445 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000446 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000447 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000448
Ted Kremenekcf118d42009-02-04 23:49:09 +0000449 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000450 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
451 }
452};
Mike Stump1eb44332009-09-09 15:08:12 +0000453
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000454} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000455
Ted Kremenek78d46242008-07-22 16:21:24 +0000456//===----------------------------------------------------------------------===//
457// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000458//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000459
460void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000461 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
462 // are different than what probably many checks will do since they don't
463 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
464 // analyzing a function. Generation of BugReport objects is done via a call
465 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000466 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000467 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000468 BR.Register(new RetStack(this));
469 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000470 BR.Register(new BadMsgExprArg(this));
471 BR.Register(new BadReceiver(this));
472 BR.Register(new OutOfBoundMemoryAccess(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000473 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000474 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000475
Ted Kremenekcf118d42009-02-04 23:49:09 +0000476 // The following checks do not need to have their associated BugTypes
477 // explicitly registered with the BugReporter. If they issue any BugReports,
478 // their associated BugType will get registered with the BugReporter
479 // automatically. Note that the check itself is owned by the GRExprEngine
480 // object.
Zhongxing Xu94943b62009-11-03 07:35:33 +0000481 registerCheck<AttrNonNullChecker>(new AttrNonNullChecker());
Zhongxing Xu8958fff2009-11-03 06:46:03 +0000482 registerCheck<UndefinedArgChecker>(new UndefinedArgChecker());
Zhongxing Xu4f64e5f2009-11-03 05:48:04 +0000483 registerCheck<BadCallChecker>(new BadCallChecker());
Zhongxing Xu9e56d232009-10-31 10:02:37 +0000484 registerCheck<DivZeroChecker>(new DivZeroChecker());
Zhongxing Xu246a9ad2009-10-31 08:44:33 +0000485 registerCheck<UndefDerefChecker>(new UndefDerefChecker());
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000486 registerCheck<NullDerefChecker>(new NullDerefChecker());
Zhongxing Xu5206f0b2009-11-03 12:13:38 +0000487 registerCheck<UndefSizedVLAChecker>(new UndefSizedVLAChecker());
488 registerCheck<ZeroSizedVLAChecker>(new ZeroSizedVLAChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000489}