blob: 66e021095ad0314b8f7ad121cb3b9bf39d3756fc [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"
Zhongxing Xu4f64e5f2009-11-03 05:48:04 +000019#include "clang/Analysis/PathSensitive/Checkers/BadCallChecker.h"
Zhongxing Xu8958fff2009-11-03 06:46:03 +000020#include "clang/Analysis/PathSensitive/Checkers/UndefinedArgChecker.h"
Ted Kremenekb107c4b2009-11-04 04:24:16 +000021#include "clang/Analysis/PathSensitive/Checkers/UndefinedAssignmentChecker.h"
Zhongxing Xu94943b62009-11-03 07:35:33 +000022#include "clang/Analysis/PathSensitive/Checkers/AttrNonNullChecker.h"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000023#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000024#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000025#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000026#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000027
28using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000029using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000030
31//===----------------------------------------------------------------------===//
32// Utility functions.
33//===----------------------------------------------------------------------===//
34
35template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000036ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000037 return *I;
38}
39
40template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000041ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000042 return I->first;
43}
44
45//===----------------------------------------------------------------------===//
46// Bug Descriptions.
47//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000048namespace clang {
49class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000050public:
51 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000052 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000053 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000054
Ted Kremenek85ac9342009-05-15 05:25:09 +000055 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000056 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000057 : RangedBugReport(bt, shortDesc, desc, n) {}
58
Ted Kremenekdd986cc2009-05-07 00:45:33 +000059 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000060 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000061};
62
Zhongxing Xuec9227f2009-10-29 02:09:30 +000063void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
64 const ExplodedNode* N) {
65 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
66}
Mike Stump1eb44332009-09-09 15:08:12 +000067
Ted Kremenekdd986cc2009-05-07 00:45:33 +000068template <typename ITER>
69void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
70 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
71 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000072}
Mike Stump1eb44332009-09-09 15:08:12 +000073
Ted Kremenek0c313172009-05-13 19:16:35 +000074class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000075public:
76 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000077 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000078
Ted Kremenek0c313172009-05-13 19:16:35 +000079 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000080 for (GRExprEngine::nil_receiver_struct_ret_iterator
81 I=Eng.nil_receiver_struct_ret_begin(),
82 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
83
84 std::string sbuf;
85 llvm::raw_string_ostream os(sbuf);
86 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000087 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000088 os << "The receiver in the message expression is 'nil' and results in the"
89 " returned value (of type '"
90 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000091 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000092
Ted Kremenek0c313172009-05-13 19:16:35 +000093 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000094 R->addRange(ME->getReceiver()->getSourceRange());
95 BR.EmitReport(R);
96 }
97 }
Mike Stump1eb44332009-09-09 15:08:12 +000098
Ted Kremenek0c313172009-05-13 19:16:35 +000099 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000100 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000101 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000102 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000103 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000104};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000105
Ted Kremenek0c313172009-05-13 19:16:35 +0000106class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000107public:
108 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000109 BuiltinBug(eng,
110 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000111
Ted Kremenek0c313172009-05-13 19:16:35 +0000112 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000113 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
114 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
115 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000116
Ted Kremenek899b3de2009-04-08 03:07:17 +0000117 std::string sbuf;
118 llvm::raw_string_ostream os(sbuf);
119 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000120 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000121 os << "The receiver in the message expression is 'nil' and results in the"
122 " returned value (of type '"
123 << ME->getType().getAsString()
124 << "' and of size "
125 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000126 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000127
Ted Kremenek0c313172009-05-13 19:16:35 +0000128 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000129 R->addRange(ME->getReceiver()->getSourceRange());
130 BR.EmitReport(R);
131 }
Mike Stump1eb44332009-09-09 15:08:12 +0000132 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000133 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000134 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000135 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000136 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000137 }
138};
Mike Stump1eb44332009-09-09 15:08:12 +0000139
Ted Kremenek78d46242008-07-22 16:21:24 +0000140class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
141public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000142 UndefResult(GRExprEngine* eng)
143 : BuiltinBug(eng,"Undefined or garbage result",
144 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000145
Ted Kremenekcf118d42009-02-04 23:49:09 +0000146 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000147 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
148 E = Eng.undef_results_end(); I!=E; ++I) {
149
150 ExplodedNode *N = *I;
151 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
152 BuiltinBugReport *report = NULL;
153
154 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
155 llvm::SmallString<256> sbuf;
156 llvm::raw_svector_ostream OS(sbuf);
157 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000158 const Expr *Ex = NULL;
159 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000160
161 if (ST->getSVal(B->getLHS()).isUndef()) {
162 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000163 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000164 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000165 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000166 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000167 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000168 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000169
170 if (Ex) {
171 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000172 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000173 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000174 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000175 }
176 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000177 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000178 OS << "The result of the '"
179 << BinaryOperator::getOpcodeStr(B->getOpcode())
180 << "' expression is undefined";
181 }
182
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000183 // FIXME: Use StringRefs to pass string information.
184 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000185 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000186 }
187 else {
188 report = new BuiltinBugReport(*this,
189 "Expression evaluates to an uninitialized"
190 " or undefined value", N);
191 }
192
193 BR.EmitReport(report);
194 }
195 }
196
197 void registerInitialVisitors(BugReporterContext& BRC,
198 const ExplodedNode* N,
199 BuiltinBugReport *R) {
200
201 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
202 const Stmt *X = S;
203
204 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
205 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000206 if (ST->getSVal(B->getLHS()).isUndef())
207 X = B->getLHS();
208 else if (ST->getSVal(B->getRHS()).isUndef())
209 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000210 }
211
212 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000213 }
214};
Mike Stump1eb44332009-09-09 15:08:12 +0000215
Ted Kremenek85ac9342009-05-15 05:25:09 +0000216class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
217 const Stmt *Arg;
218public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000219 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000220 const Stmt *arg)
221 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000222
Ted Kremenek85ac9342009-05-15 05:25:09 +0000223 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000224 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000225 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
226
227 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000228};
229
230class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000231public:
232 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000233 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000234
Ted Kremenekcf118d42009-02-04 23:49:09 +0000235 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000236 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000237
Ted Kremenek85ac9342009-05-15 05:25:09 +0000238 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000239 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000240 BuiltinBugReport *R) {
241 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
242 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000243 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000244};
Mike Stump1eb44332009-09-09 15:08:12 +0000245
Ted Kremenek78d46242008-07-22 16:21:24 +0000246class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
247public:
Mike Stump1eb44332009-09-09 15:08:12 +0000248 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000249 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000250
Ted Kremenekcf118d42009-02-04 23:49:09 +0000251 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000252 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000253 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000254 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000255 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
256 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000257 report->addRange(I->second->getSourceRange());
258 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000259 }
260 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000261};
Mike Stump1eb44332009-09-09 15:08:12 +0000262
Ted Kremenek78d46242008-07-22 16:21:24 +0000263class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000264public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000265 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000266 : BuiltinBug(eng,"Uninitialized receiver",
267 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000268
Ted Kremenekcf118d42009-02-04 23:49:09 +0000269 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000270 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000271 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000272
Ted Kremenek78d46242008-07-22 16:21:24 +0000273 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000274 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000275 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000276 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
277 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000278 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000279 report->addRange(E->getSourceRange());
280 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000281 }
282 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000283
Ted Kremenek0c313172009-05-13 19:16:35 +0000284 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000285 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000286 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000287 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000288 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000289};
Ted Kremenek5917d782008-11-21 00:27:44 +0000290
Ted Kremenek78d46242008-07-22 16:21:24 +0000291class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
292 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000293 GRStateManager& VM;
294 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000295
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000296 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000297
298 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000299 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000300 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000301
Ted Kremenekb7714b22008-07-30 17:49:12 +0000302 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000303 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
304 Expr* E2 = FindExpr(ExI);
305 if (E2) return E2;
306 }
Mike Stump1eb44332009-09-09 15:08:12 +0000307
Ted Kremenek78d46242008-07-22 16:21:24 +0000308 return Ex;
309 }
Mike Stump1eb44332009-09-09 15:08:12 +0000310
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000311 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000312 };
Mike Stump1eb44332009-09-09 15:08:12 +0000313
Ted Kremenek78d46242008-07-22 16:21:24 +0000314public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000315 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000316 : BuiltinBug(eng,"Use of garbage value",
317 "Branch condition evaluates to an undefined or garbage value")
318 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000319
Ted Kremenekcf118d42009-02-04 23:49:09 +0000320 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000321 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
322 E=Eng.undef_branches_end(); I!=E; ++I) {
323
324 // What's going on here: we want to highlight the subexpression of the
325 // condition that is the most likely source of the "uninitialized
326 // branch condition." We do a recursive walk of the condition's
327 // subexpressions and roughly look for the most nested subexpression
328 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000329 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
330 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
331 assert (Ex && "Block must have a terminator.");
332
333 // Get the predecessor node and check if is a PostStmt with the Stmt
334 // being the terminator condition. We want to inspect the state
335 // of that node instead because it will contain main information about
336 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000337 assert (!(*I)->pred_empty());
338
339 // Note: any predecessor will do. They should have identical state,
340 // since all the BlockEdge did was act as an error sink since the value
341 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000342 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000343 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000344 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000345
346 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
347 if (PS->getStmt() == Ex)
348 St = N->getState();
349
350 FindUndefExpr FindIt(Eng.getStateManager(), St);
351 Ex = FindIt.FindExpr(Ex);
352
Ted Kremenek85ac9342009-05-15 05:25:09 +0000353 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000354 R->addRange(Ex->getSourceRange());
355 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000356 }
357 }
Mike Stump1eb44332009-09-09 15:08:12 +0000358
Ted Kremenek85ac9342009-05-15 05:25:09 +0000359 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000360 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000361 BuiltinBugReport *R) {
362 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
363 N);
364 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000365};
366
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000367class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
368public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000369 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000370 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000371 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000372
Ted Kremenekcf118d42009-02-04 23:49:09 +0000373 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000374 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
375 }
376};
Mike Stump1eb44332009-09-09 15:08:12 +0000377
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000378} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000379
Ted Kremenek78d46242008-07-22 16:21:24 +0000380//===----------------------------------------------------------------------===//
381// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000382//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000383
384void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000385 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
386 // are different than what probably many checks will do since they don't
387 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
388 // analyzing a function. Generation of BugReport objects is done via a call
389 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000390 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000391 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000392 BR.Register(new BadMsgExprArg(this));
393 BR.Register(new BadReceiver(this));
394 BR.Register(new OutOfBoundMemoryAccess(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000395 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000396 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000397
Ted Kremenekcf118d42009-02-04 23:49:09 +0000398 // The following checks do not need to have their associated BugTypes
399 // explicitly registered with the BugReporter. If they issue any BugReports,
400 // their associated BugType will get registered with the BugReporter
401 // automatically. Note that the check itself is owned by the GRExprEngine
Ted Kremenek36df58a2009-11-06 20:47:51 +0000402 // object.
Ted Kremenekb107c4b2009-11-04 04:24:16 +0000403 registerCheck(new AttrNonNullChecker());
404 registerCheck(new UndefinedArgChecker());
405 registerCheck(new UndefinedAssignmentChecker());
406 registerCheck(new BadCallChecker());
Ted Kremenek84b35952009-11-06 21:51:50 +0000407
Ted Kremenekb4b817d2009-11-11 03:26:34 +0000408 RegisterDereferenceChecker(*this);
Ted Kremenek84b35952009-11-06 21:51:50 +0000409 RegisterVLASizeChecker(*this);
410 RegisterDivZeroChecker(*this);
411 RegisterReturnStackAddressChecker(*this);
412 RegisterReturnUndefChecker(*this);
Zhongxing Xu3ce2dc32009-11-09 05:34:10 +0000413 RegisterPointerSubChecker(*this);
Zhongxing Xuede7eb22009-11-09 13:23:31 +0000414 RegisterPointerArithChecker(*this);
Zhongxing Xub10a7c22009-11-09 06:52:44 +0000415 RegisterFixedAddressChecker(*this);
Ted Kremenek84b35952009-11-06 21:51:50 +0000416 // Note that this must be registered after ReturnStackAddressChecker.
417 RegisterReturnPointerRangeChecker(*this);
Zhongxing Xu4f3dc692009-11-09 08:07:38 +0000418
419 RegisterCastToStructChecker(*this);
Ted Kremenek78d46242008-07-22 16:21:24 +0000420}