blob: 3daf3c8ef59cad4e1a2299c3f2d581ac47d5f53d [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
Ted Kremenek1053d242009-11-06 02:24:13 +000015#include "GRExprEngineInternalChecks.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000016#include "clang/Analysis/PathSensitive/BugReporter.h"
17#include "clang/Analysis/PathSensitive/GRExprEngine.h"
Ted Kremenekc26a8b02009-07-22 21:46:56 +000018#include "clang/Analysis/PathSensitive/CheckerVisitor.h"
Ted Kremenekdc998c12009-11-03 18:41:06 +000019#include "clang/Analysis/PathSensitive/Checkers/DereferenceChecker.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 UndefBranch : public BuiltinBug {
294 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000295 GRStateManager& VM;
296 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000297
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000298 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000299
300 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000301 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000302 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000303
Ted Kremenekb7714b22008-07-30 17:49:12 +0000304 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000305 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
306 Expr* E2 = FindExpr(ExI);
307 if (E2) return E2;
308 }
Mike Stump1eb44332009-09-09 15:08:12 +0000309
Ted Kremenek78d46242008-07-22 16:21:24 +0000310 return Ex;
311 }
Mike Stump1eb44332009-09-09 15:08:12 +0000312
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000313 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000314 };
Mike Stump1eb44332009-09-09 15:08:12 +0000315
Ted Kremenek78d46242008-07-22 16:21:24 +0000316public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000317 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000318 : BuiltinBug(eng,"Use of garbage value",
319 "Branch condition evaluates to an undefined or garbage value")
320 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000321
Ted Kremenekcf118d42009-02-04 23:49:09 +0000322 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000323 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
324 E=Eng.undef_branches_end(); I!=E; ++I) {
325
326 // What's going on here: we want to highlight the subexpression of the
327 // condition that is the most likely source of the "uninitialized
328 // branch condition." We do a recursive walk of the condition's
329 // subexpressions and roughly look for the most nested subexpression
330 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000331 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
332 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
333 assert (Ex && "Block must have a terminator.");
334
335 // Get the predecessor node and check if is a PostStmt with the Stmt
336 // being the terminator condition. We want to inspect the state
337 // of that node instead because it will contain main information about
338 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000339 assert (!(*I)->pred_empty());
340
341 // Note: any predecessor will do. They should have identical state,
342 // since all the BlockEdge did was act as an error sink since the value
343 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000344 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000345 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000346 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000347
348 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
349 if (PS->getStmt() == Ex)
350 St = N->getState();
351
352 FindUndefExpr FindIt(Eng.getStateManager(), St);
353 Ex = FindIt.FindExpr(Ex);
354
Ted Kremenek85ac9342009-05-15 05:25:09 +0000355 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000356 R->addRange(Ex->getSourceRange());
357 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000358 }
359 }
Mike Stump1eb44332009-09-09 15:08:12 +0000360
Ted Kremenek85ac9342009-05-15 05:25:09 +0000361 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000362 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000363 BuiltinBugReport *R) {
364 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
365 N);
366 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000367};
368
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000369class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
370public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000371 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000372 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000373 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000374
Ted Kremenekcf118d42009-02-04 23:49:09 +0000375 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000376 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
377 }
378};
Mike Stump1eb44332009-09-09 15:08:12 +0000379
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000380} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000381
Ted Kremenek78d46242008-07-22 16:21:24 +0000382//===----------------------------------------------------------------------===//
383// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000384//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000385
386void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000387 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
388 // are different than what probably many checks will do since they don't
389 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
390 // analyzing a function. Generation of BugReport objects is done via a call
391 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000392 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000393 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000394 BR.Register(new BadMsgExprArg(this));
395 BR.Register(new BadReceiver(this));
396 BR.Register(new OutOfBoundMemoryAccess(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000397 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000398 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000399
Ted Kremenek36df58a2009-11-06 20:47:51 +0000400 RegisterDivZeroChecker(*this);
401 RegisterReturnStackAddressChecker(*this);
402 RegisterReturnUndefChecker(*this);
403
404 // Note that this must be registered after ReturnStackAddressChecker.
405 RegisterReturnPointerRangeChecker(*this);
406
Ted Kremenekcf118d42009-02-04 23:49:09 +0000407 // The following checks do not need to have their associated BugTypes
408 // explicitly registered with the BugReporter. If they issue any BugReports,
409 // their associated BugType will get registered with the BugReporter
410 // automatically. Note that the check itself is owned by the GRExprEngine
Ted Kremenek36df58a2009-11-06 20:47:51 +0000411 // object.
Ted Kremenekb107c4b2009-11-04 04:24:16 +0000412 registerCheck(new AttrNonNullChecker());
413 registerCheck(new UndefinedArgChecker());
414 registerCheck(new UndefinedAssignmentChecker());
415 registerCheck(new BadCallChecker());
Ted Kremenekb107c4b2009-11-04 04:24:16 +0000416 registerCheck(new UndefDerefChecker());
417 registerCheck(new NullDerefChecker());
418 registerCheck(new UndefSizedVLAChecker());
419 registerCheck(new ZeroSizedVLAChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000420}