blob: 695f0b02e59713c510a4d764bbc3a10843acbf99 [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 Kremenekdc998c12009-11-03 18:41:06 +000018#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.h"
Zhongxing Xu9e56d232009-10-31 10:02:37 +000019#include "clang/Analysis/PathSensitive/Checkers/DivZeroChecker.h"
Zhongxing Xu4f64e5f2009-11-03 05:48:04 +000020#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
Zhongxing Xu8958fff2009-11-03 06:46:03 +000021#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
Ted Kremenekb107c4b2009-11-04 04:24:16 +000022#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
Zhongxing Xu94943b62009-11-03 07:35:33 +000023#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
Zhongxing Xu05a23382009-11-04 01:43:07 +000024#include "clang/Analysis/PathSensitive/Checkers/VLASizeChecker.h"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000025#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000026#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000027#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000028#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000029
30using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000031using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000032
33//===----------------------------------------------------------------------===//
34// Utility functions.
35//===----------------------------------------------------------------------===//
36
37template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000038ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000039 return *I;
40}
41
42template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000043ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000044 return I->first;
45}
46
47//===----------------------------------------------------------------------===//
48// Bug Descriptions.
49//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000050namespace clang {
51class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000052public:
53 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000054 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000055 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000056
Ted Kremenek85ac9342009-05-15 05:25:09 +000057 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000058 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000059 : RangedBugReport(bt, shortDesc, desc, n) {}
60
Ted Kremenekdd986cc2009-05-07 00:45:33 +000061 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000062 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000063};
64
Zhongxing Xuec9227f2009-10-29 02:09:30 +000065void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
66 const ExplodedNode* N) {
67 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
68}
Mike Stump1eb44332009-09-09 15:08:12 +000069
Ted Kremenekdd986cc2009-05-07 00:45:33 +000070template <typename ITER>
71void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
72 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
73 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000074}
Mike Stump1eb44332009-09-09 15:08:12 +000075
Ted Kremenek0c313172009-05-13 19:16:35 +000076class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000077public:
78 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000079 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000080
Ted Kremenek0c313172009-05-13 19:16:35 +000081 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000082 for (GRExprEngine::nil_receiver_struct_ret_iterator
83 I=Eng.nil_receiver_struct_ret_begin(),
84 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
85
86 std::string sbuf;
87 llvm::raw_string_ostream os(sbuf);
88 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000089 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000090 os << "The receiver in the message expression is 'nil' and results in the"
91 " returned value (of type '"
92 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000093 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000094
Ted Kremenek0c313172009-05-13 19:16:35 +000095 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000096 R->addRange(ME->getReceiver()->getSourceRange());
97 BR.EmitReport(R);
98 }
99 }
Mike Stump1eb44332009-09-09 15:08:12 +0000100
Ted Kremenek0c313172009-05-13 19:16:35 +0000101 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000102 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000103 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000104 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000105 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000106};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000107
Ted Kremenek0c313172009-05-13 19:16:35 +0000108class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000109public:
110 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000111 BuiltinBug(eng,
112 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000113
Ted Kremenek0c313172009-05-13 19:16:35 +0000114 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000115 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
116 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
117 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000118
Ted Kremenek899b3de2009-04-08 03:07:17 +0000119 std::string sbuf;
120 llvm::raw_string_ostream os(sbuf);
121 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000122 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000123 os << "The receiver in the message expression is 'nil' and results in the"
124 " returned value (of type '"
125 << ME->getType().getAsString()
126 << "' and of size "
127 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000128 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000129
Ted Kremenek0c313172009-05-13 19:16:35 +0000130 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000131 R->addRange(ME->getReceiver()->getSourceRange());
132 BR.EmitReport(R);
133 }
Mike Stump1eb44332009-09-09 15:08:12 +0000134 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000135 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000136 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000137 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000138 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000139 }
140};
Mike Stump1eb44332009-09-09 15:08:12 +0000141
Ted Kremenek78d46242008-07-22 16:21:24 +0000142class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
143public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000144 UndefResult(GRExprEngine* eng)
145 : BuiltinBug(eng,"Undefined or garbage result",
146 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000147
Ted Kremenekcf118d42009-02-04 23:49:09 +0000148 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000149 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
150 E = Eng.undef_results_end(); I!=E; ++I) {
151
152 ExplodedNode *N = *I;
153 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
154 BuiltinBugReport *report = NULL;
155
156 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
157 llvm::SmallString<256> sbuf;
158 llvm::raw_svector_ostream OS(sbuf);
159 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000160 const Expr *Ex = NULL;
161 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000162
163 if (ST->getSVal(B->getLHS()).isUndef()) {
164 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000165 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000166 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000167 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000168 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000169 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000170 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000171
172 if (Ex) {
173 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000174 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000175 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000176 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000177 }
178 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000179 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000180 OS << "The result of the '"
181 << BinaryOperator::getOpcodeStr(B->getOpcode())
182 << "' expression is undefined";
183 }
184
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000185 // FIXME: Use StringRefs to pass string information.
186 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000187 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000188 }
189 else {
190 report = new BuiltinBugReport(*this,
191 "Expression evaluates to an uninitialized"
192 " or undefined value", N);
193 }
194
195 BR.EmitReport(report);
196 }
197 }
198
199 void registerInitialVisitors(BugReporterContext& BRC,
200 const ExplodedNode* N,
201 BuiltinBugReport *R) {
202
203 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
204 const Stmt *X = S;
205
206 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
207 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000208 if (ST->getSVal(B->getLHS()).isUndef())
209 X = B->getLHS();
210 else if (ST->getSVal(B->getRHS()).isUndef())
211 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000212 }
213
214 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000215 }
216};
Mike Stump1eb44332009-09-09 15:08:12 +0000217
Ted Kremenek85ac9342009-05-15 05:25:09 +0000218class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
219 const Stmt *Arg;
220public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000221 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000222 const Stmt *arg)
223 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000224
Ted Kremenek85ac9342009-05-15 05:25:09 +0000225 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000226 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000227 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
228
229 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000230};
231
232class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000233public:
234 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000235 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000236
Ted Kremenekcf118d42009-02-04 23:49:09 +0000237 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000238 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000239
Ted Kremenek85ac9342009-05-15 05:25:09 +0000240 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000241 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000242 BuiltinBugReport *R) {
243 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
244 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000245 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000246};
Mike Stump1eb44332009-09-09 15:08:12 +0000247
Ted Kremenek78d46242008-07-22 16:21:24 +0000248class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
249public:
Mike Stump1eb44332009-09-09 15:08:12 +0000250 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000251 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000252
Ted Kremenekcf118d42009-02-04 23:49:09 +0000253 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000254 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000255 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000256 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000257 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
258 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000259 report->addRange(I->second->getSourceRange());
260 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000261 }
262 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000263};
Mike Stump1eb44332009-09-09 15:08:12 +0000264
Ted Kremenek78d46242008-07-22 16:21:24 +0000265class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000266public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000267 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000268 : BuiltinBug(eng,"Uninitialized receiver",
269 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000270
Ted Kremenekcf118d42009-02-04 23:49:09 +0000271 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000272 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000273 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000274
Ted Kremenek78d46242008-07-22 16:21:24 +0000275 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000276 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000277 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000278 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
279 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000280 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000281 report->addRange(E->getSourceRange());
282 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000283 }
284 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000285
Ted Kremenek0c313172009-05-13 19:16:35 +0000286 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000287 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000288 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000289 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000290 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000291};
Ted Kremenek5917d782008-11-21 00:27:44 +0000292
Ted Kremenek78d46242008-07-22 16:21:24 +0000293class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
294public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000295 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000296 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000297
Ted Kremenekcf118d42009-02-04 23:49:09 +0000298 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000299 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
300 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000301
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000302 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000303 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
304 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
305 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000306
Ted Kremenek22bda882008-07-31 20:31:27 +0000307 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000308 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000309
Ted Kremenek22bda882008-07-31 20:31:27 +0000310 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000311 std::string buf;
312 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000313 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000314
Ted Kremenek8aed8062008-10-31 00:13:20 +0000315 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000316 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000317 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000318
Ted Kremenek8aed8062008-10-31 00:13:20 +0000319 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
320 os << "Address of stack memory associated with a compound literal "
321 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000322 << BR.getSourceManager()
323 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000324 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000325
Ted Kremenek8aed8062008-10-31 00:13:20 +0000326 R = CL->getSourceRange();
327 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000328 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
329 const Expr* ARE = AR->getExpr();
330 SourceLocation L = ARE->getLocStart();
331 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000332
Ted Kremenekde8cd192008-11-02 00:35:25 +0000333 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000334 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000335 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000336 }
337 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000338 os << "Address of stack memory associated with local variable '"
339 << V.getRegion()->getString() << "' returned.";
340 }
Mike Stump1eb44332009-09-09 15:08:12 +0000341
Ted Kremenekcf118d42009-02-04 23:49:09 +0000342 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
343 report->addRange(E->getSourceRange());
344 if (R.isValid()) report->addRange(R);
345 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000346 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000347 }
348};
Mike Stump1eb44332009-09-09 15:08:12 +0000349
Ted Kremenek5917d782008-11-21 00:27:44 +0000350class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
351public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000352 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
353 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000354
Ted Kremenekcf118d42009-02-04 23:49:09 +0000355 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000356 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
357 }
Mike Stump1eb44332009-09-09 15:08:12 +0000358
Ted Kremenek0c313172009-05-13 19:16:35 +0000359 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000360 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000361 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000362 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000363 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000364};
Ted Kremenek78d46242008-07-22 16:21:24 +0000365
366class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
367 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000368 GRStateManager& VM;
369 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000370
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000371 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000372
373 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000374 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000375 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000376
Ted Kremenekb7714b22008-07-30 17:49:12 +0000377 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000378 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
379 Expr* E2 = FindExpr(ExI);
380 if (E2) return E2;
381 }
Mike Stump1eb44332009-09-09 15:08:12 +0000382
Ted Kremenek78d46242008-07-22 16:21:24 +0000383 return Ex;
384 }
Mike Stump1eb44332009-09-09 15:08:12 +0000385
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000386 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000387 };
Mike Stump1eb44332009-09-09 15:08:12 +0000388
Ted Kremenek78d46242008-07-22 16:21:24 +0000389public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000390 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000391 : BuiltinBug(eng,"Use of garbage value",
392 "Branch condition evaluates to an undefined or garbage value")
393 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000394
Ted Kremenekcf118d42009-02-04 23:49:09 +0000395 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000396 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
397 E=Eng.undef_branches_end(); I!=E; ++I) {
398
399 // What's going on here: we want to highlight the subexpression of the
400 // condition that is the most likely source of the "uninitialized
401 // branch condition." We do a recursive walk of the condition's
402 // subexpressions and roughly look for the most nested subexpression
403 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000404 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
405 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
406 assert (Ex && "Block must have a terminator.");
407
408 // Get the predecessor node and check if is a PostStmt with the Stmt
409 // being the terminator condition. We want to inspect the state
410 // of that node instead because it will contain main information about
411 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000412 assert (!(*I)->pred_empty());
413
414 // Note: any predecessor will do. They should have identical state,
415 // since all the BlockEdge did was act as an error sink since the value
416 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000417 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000418 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000419 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000420
421 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
422 if (PS->getStmt() == Ex)
423 St = N->getState();
424
425 FindUndefExpr FindIt(Eng.getStateManager(), St);
426 Ex = FindIt.FindExpr(Ex);
427
Ted Kremenek85ac9342009-05-15 05:25:09 +0000428 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000429 R->addRange(Ex->getSourceRange());
430 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000431 }
432 }
Mike Stump1eb44332009-09-09 15:08:12 +0000433
Ted Kremenek85ac9342009-05-15 05:25:09 +0000434 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000435 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000436 BuiltinBugReport *R) {
437 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
438 N);
439 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000440};
441
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000442class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
443public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000444 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000445 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000446 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000447
Ted Kremenekcf118d42009-02-04 23:49:09 +0000448 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000449 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
450 }
451};
Mike Stump1eb44332009-09-09 15:08:12 +0000452
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000453} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000454
Ted Kremenek78d46242008-07-22 16:21:24 +0000455//===----------------------------------------------------------------------===//
456// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000457//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000458
459void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000460 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
461 // are different than what probably many checks will do since they don't
462 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
463 // analyzing a function. Generation of BugReport objects is done via a call
464 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000465 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000466 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000467 BR.Register(new RetStack(this));
468 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000469 BR.Register(new BadMsgExprArg(this));
470 BR.Register(new BadReceiver(this));
471 BR.Register(new OutOfBoundMemoryAccess(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000472 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000473 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000474
Ted Kremenekcf118d42009-02-04 23:49:09 +0000475 // The following checks do not need to have their associated BugTypes
476 // explicitly registered with the BugReporter. If they issue any BugReports,
477 // their associated BugType will get registered with the BugReporter
478 // automatically. Note that the check itself is owned by the GRExprEngine
479 // object.
Ted Kremenekb107c4b2009-11-04 04:24:16 +0000480 registerCheck(new AttrNonNullChecker());
481 registerCheck(new UndefinedArgChecker());
482 registerCheck(new UndefinedAssignmentChecker());
483 registerCheck(new BadCallChecker());
484 registerCheck(new DivZeroChecker());
485 registerCheck(new UndefDerefChecker());
486 registerCheck(new NullDerefChecker());
487 registerCheck(new UndefSizedVLAChecker());
488 registerCheck(new ZeroSizedVLAChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000489}