blob: 239d04c09b75ff97dae1f30e4a0d89a50392cef6 [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"
Ted Kremenekdd986cc2009-05-07 00:45:33 +000019#include "clang/Analysis/PathDiagnostic.h"
Ted Kremenek8aed8062008-10-31 00:13:20 +000020#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000021#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000022#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000023
24using namespace clang;
Ted Kremenek53500662009-07-22 17:55:28 +000025using namespace clang::bugreporter;
Ted Kremenek78d46242008-07-22 16:21:24 +000026
27//===----------------------------------------------------------------------===//
28// Utility functions.
29//===----------------------------------------------------------------------===//
30
31template <typename ITERATOR> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000032ExplodedNode* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000033 return *I;
34}
35
36template <> inline
Zhongxing Xuc5619d92009-08-06 01:32:16 +000037ExplodedNode* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000038 return I->first;
39}
40
41//===----------------------------------------------------------------------===//
42// Bug Descriptions.
43//===----------------------------------------------------------------------===//
Zhongxing Xuec9227f2009-10-29 02:09:30 +000044namespace clang {
45class BuiltinBugReport : public RangedBugReport {
Ted Kremenekdd986cc2009-05-07 00:45:33 +000046public:
47 BuiltinBugReport(BugType& bt, const char* desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000048 ExplodedNode *n)
Ted Kremenek0c313172009-05-13 19:16:35 +000049 : RangedBugReport(bt, desc, n) {}
Mike Stump1eb44332009-09-09 15:08:12 +000050
Ted Kremenek85ac9342009-05-15 05:25:09 +000051 BuiltinBugReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000052 ExplodedNode *n)
Mike Stump1eb44332009-09-09 15:08:12 +000053 : RangedBugReport(bt, shortDesc, desc, n) {}
54
Ted Kremenekdd986cc2009-05-07 00:45:33 +000055 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000056 const ExplodedNode* N);
Mike Stump1eb44332009-09-09 15:08:12 +000057};
58
Zhongxing Xuec9227f2009-10-29 02:09:30 +000059void BuiltinBugReport::registerInitialVisitors(BugReporterContext& BRC,
60 const ExplodedNode* N) {
61 static_cast<BuiltinBug&>(getBugType()).registerInitialVisitors(BRC, N, this);
62}
Mike Stump1eb44332009-09-09 15:08:12 +000063
Ted Kremenekdd986cc2009-05-07 00:45:33 +000064template <typename ITER>
65void BuiltinBug::Emit(BugReporter& BR, ITER I, ITER E) {
66 for (; I != E; ++I) BR.EmitReport(new BuiltinBugReport(*this, desc.c_str(),
67 GetNode(I)));
Mike Stump1eb44332009-09-09 15:08:12 +000068}
Mike Stump1eb44332009-09-09 15:08:12 +000069
Ted Kremenek0c313172009-05-13 19:16:35 +000070class VISIBILITY_HIDDEN NilReceiverStructRet : public BuiltinBug {
Ted Kremenek21fe8372009-02-19 04:06:22 +000071public:
72 NilReceiverStructRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +000073 BuiltinBug(eng, "'nil' receiver with struct return type") {}
Ted Kremenek21fe8372009-02-19 04:06:22 +000074
Ted Kremenek0c313172009-05-13 19:16:35 +000075 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek21fe8372009-02-19 04:06:22 +000076 for (GRExprEngine::nil_receiver_struct_ret_iterator
77 I=Eng.nil_receiver_struct_ret_begin(),
78 E=Eng.nil_receiver_struct_ret_end(); I!=E; ++I) {
79
80 std::string sbuf;
81 llvm::raw_string_ostream os(sbuf);
82 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +000083 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek21fe8372009-02-19 04:06:22 +000084 os << "The receiver in the message expression is 'nil' and results in the"
85 " returned value (of type '"
86 << ME->getType().getAsString()
Ted Kremenek5b9bd212009-09-11 22:07:28 +000087 << "') to be garbage or otherwise undefined";
Ted Kremenek21fe8372009-02-19 04:06:22 +000088
Ted Kremenek0c313172009-05-13 19:16:35 +000089 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek21fe8372009-02-19 04:06:22 +000090 R->addRange(ME->getReceiver()->getSourceRange());
91 BR.EmitReport(R);
92 }
93 }
Mike Stump1eb44332009-09-09 15:08:12 +000094
Ted Kremenek0c313172009-05-13 19:16:35 +000095 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +000096 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +000097 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +000098 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +000099 }
Ted Kremenek21fe8372009-02-19 04:06:22 +0000100};
Ted Kremenek899b3de2009-04-08 03:07:17 +0000101
Ted Kremenek0c313172009-05-13 19:16:35 +0000102class VISIBILITY_HIDDEN NilReceiverLargerThanVoidPtrRet : public BuiltinBug {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000103public:
104 NilReceiverLargerThanVoidPtrRet(GRExprEngine* eng) :
Ted Kremenek0c313172009-05-13 19:16:35 +0000105 BuiltinBug(eng,
106 "'nil' receiver with return type larger than sizeof(void *)") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000107
Ted Kremenek0c313172009-05-13 19:16:35 +0000108 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek899b3de2009-04-08 03:07:17 +0000109 for (GRExprEngine::nil_receiver_larger_than_voidptr_ret_iterator
110 I=Eng.nil_receiver_larger_than_voidptr_ret_begin(),
111 E=Eng.nil_receiver_larger_than_voidptr_ret_end(); I!=E; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000112
Ted Kremenek899b3de2009-04-08 03:07:17 +0000113 std::string sbuf;
114 llvm::raw_string_ostream os(sbuf);
115 PostStmt P = cast<PostStmt>((*I)->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000116 const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(P.getStmt());
Ted Kremenek899b3de2009-04-08 03:07:17 +0000117 os << "The receiver in the message expression is 'nil' and results in the"
118 " returned value (of type '"
119 << ME->getType().getAsString()
120 << "' and of size "
121 << Eng.getContext().getTypeSize(ME->getType()) / 8
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000122 << " bytes) to be garbage or otherwise undefined";
Mike Stump1eb44332009-09-09 15:08:12 +0000123
Ted Kremenek0c313172009-05-13 19:16:35 +0000124 BuiltinBugReport *R = new BuiltinBugReport(*this, os.str().c_str(), *I);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000125 R->addRange(ME->getReceiver()->getSourceRange());
126 BR.EmitReport(R);
127 }
Mike Stump1eb44332009-09-09 15:08:12 +0000128 }
Ted Kremenek0c313172009-05-13 19:16:35 +0000129 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000130 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000131 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000132 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Ted Kremenek899b3de2009-04-08 03:07:17 +0000133 }
134};
Mike Stump1eb44332009-09-09 15:08:12 +0000135
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000136
137
Ted Kremenek78d46242008-07-22 16:21:24 +0000138class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
139public:
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000140 UndefinedDeref()
141 : BuiltinBug(0, "Dereference of undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000142
Ted Kremenek0c313172009-05-13 19:16:35 +0000143 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000144 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000145 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000146 registerTrackNullOrUndefValue(BRC, GetDerefExpr(N), N);
Ted Kremenek0c313172009-05-13 19:16:35 +0000147 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000148};
149
150class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
151public:
Zhongxing Xu6403b572009-09-02 13:26:26 +0000152 DivZero(GRExprEngine* eng = 0)
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000153 : BuiltinBug(eng,"Division by zero") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000154
Ted Kremenek85ac9342009-05-15 05:25:09 +0000155 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000156 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000157 BuiltinBugReport *R) {
158 registerTrackNullOrUndefValue(BRC, GetDenomExpr(N), N);
159 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000160};
Mike Stump1eb44332009-09-09 15:08:12 +0000161
Ted Kremenek78d46242008-07-22 16:21:24 +0000162class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
163public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000164 UndefResult(GRExprEngine* eng)
165 : BuiltinBug(eng,"Undefined or garbage result",
166 "Result of operation is garbage or undefined") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000167
Ted Kremenekcf118d42009-02-04 23:49:09 +0000168 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000169 for (GRExprEngine::undef_result_iterator I=Eng.undef_results_begin(),
170 E = Eng.undef_results_end(); I!=E; ++I) {
171
172 ExplodedNode *N = *I;
173 const Stmt *S = N->getLocationAs<PostStmt>()->getStmt();
174 BuiltinBugReport *report = NULL;
175
176 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
177 llvm::SmallString<256> sbuf;
178 llvm::raw_svector_ostream OS(sbuf);
179 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000180 const Expr *Ex = NULL;
181 bool isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000182
183 if (ST->getSVal(B->getLHS()).isUndef()) {
184 Ex = B->getLHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000185 isLeft = true;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000186 }
Ted Kremenek24c411b2009-09-15 17:43:54 +0000187 else if (ST->getSVal(B->getRHS()).isUndef()) {
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000188 Ex = B->getRHS()->IgnoreParenCasts();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000189 isLeft = false;
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000190 }
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000191
192 if (Ex) {
193 OS << "The " << (isLeft ? "left" : "right")
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000194 << " operand of '"
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000195 << BinaryOperator::getOpcodeStr(B->getOpcode())
Ted Kremenek112ba7e2009-09-24 00:44:26 +0000196 << "' is a garbage value";
Ted Kremenek24c411b2009-09-15 17:43:54 +0000197 }
198 else {
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000199 // Neither operand was undefined, but the result is undefined.
Ted Kremenek24c411b2009-09-15 17:43:54 +0000200 OS << "The result of the '"
201 << BinaryOperator::getOpcodeStr(B->getOpcode())
202 << "' expression is undefined";
203 }
204
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000205 // FIXME: Use StringRefs to pass string information.
206 report = new BuiltinBugReport(*this, OS.str().str().c_str(), N);
Ted Kremenek24c411b2009-09-15 17:43:54 +0000207 if (Ex) report->addRange(Ex->getSourceRange());
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000208 }
209 else {
210 report = new BuiltinBugReport(*this,
211 "Expression evaluates to an uninitialized"
212 " or undefined value", N);
213 }
214
215 BR.EmitReport(report);
216 }
217 }
218
219 void registerInitialVisitors(BugReporterContext& BRC,
220 const ExplodedNode* N,
221 BuiltinBugReport *R) {
222
223 const Stmt *S = N->getLocationAs<StmtPoint>()->getStmt();
224 const Stmt *X = S;
225
226 if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S)) {
227 const GRState *ST = N->getState();
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000228 if (ST->getSVal(B->getLHS()).isUndef())
229 X = B->getLHS();
230 else if (ST->getSVal(B->getRHS()).isUndef())
231 X = B->getRHS();
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000232 }
233
234 registerTrackNullOrUndefValue(BRC, X, N);
Ted Kremenek78d46242008-07-22 16:21:24 +0000235 }
236};
Mike Stump1eb44332009-09-09 15:08:12 +0000237
Ted Kremenek78d46242008-07-22 16:21:24 +0000238class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
239public:
Zhongxing Xud99f3612009-09-02 08:10:35 +0000240 BadCall(GRExprEngine *eng = 0)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000241 : BuiltinBug(eng, "Invalid function call",
Ted Kremenek17a8e072009-03-01 05:43:22 +0000242 "Called function pointer is a null or undefined pointer value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000243
Ted Kremenek85ac9342009-05-15 05:25:09 +0000244 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000245 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000246 BuiltinBugReport *R) {
247 registerTrackNullOrUndefValue(BRC, GetCalleeExpr(N), N);
248 }
249};
250
251
252class VISIBILITY_HIDDEN ArgReport : public BuiltinBugReport {
253 const Stmt *Arg;
254public:
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000255 ArgReport(BugType& bt, const char* desc, ExplodedNode *n,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000256 const Stmt *arg)
257 : BuiltinBugReport(bt, desc, n), Arg(arg) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000258
Ted Kremenek85ac9342009-05-15 05:25:09 +0000259 ArgReport(BugType& bt, const char *shortDesc, const char *desc,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000260 ExplodedNode *n, const Stmt *arg)
Mike Stump1eb44332009-09-09 15:08:12 +0000261 : BuiltinBugReport(bt, shortDesc, desc, n), Arg(arg) {}
262
263 const Stmt *getArg() const { return Arg; }
Ted Kremenek78d46242008-07-22 16:21:24 +0000264};
265
266class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000267public:
268 BadArg(GRExprEngine* eng=0) : BuiltinBug(eng,"Uninitialized argument",
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000269 "Pass-by-value argument in function call is undefined") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000270
Ted Kremenekcf118d42009-02-04 23:49:09 +0000271 BadArg(GRExprEngine* eng, const char* d)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000272 : BuiltinBug(eng,"Uninitialized argument", d) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000273
Ted Kremenek85ac9342009-05-15 05:25:09 +0000274 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000275 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000276 BuiltinBugReport *R) {
277 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
278 N);
Mike Stump1eb44332009-09-09 15:08:12 +0000279 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000280};
Mike Stump1eb44332009-09-09 15:08:12 +0000281
Ted Kremenek78d46242008-07-22 16:21:24 +0000282class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
283public:
Mike Stump1eb44332009-09-09 15:08:12 +0000284 BadMsgExprArg(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000285 : BadArg(eng,"Pass-by-value argument in message expression is undefined"){}
Mike Stump1eb44332009-09-09 15:08:12 +0000286
Ted Kremenekcf118d42009-02-04 23:49:09 +0000287 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000288 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Mike Stump1eb44332009-09-09 15:08:12 +0000289 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000290 // Generate a report for this bug.
Ted Kremenek85ac9342009-05-15 05:25:09 +0000291 ArgReport *report = new ArgReport(*this, desc.c_str(), I->first,
292 I->second);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000293 report->addRange(I->second->getSourceRange());
294 BR.EmitReport(report);
Mike Stump1eb44332009-09-09 15:08:12 +0000295 }
296 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000297};
Mike Stump1eb44332009-09-09 15:08:12 +0000298
Ted Kremenek78d46242008-07-22 16:21:24 +0000299class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
Mike Stump1eb44332009-09-09 15:08:12 +0000300public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000301 BadReceiver(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000302 : BuiltinBug(eng,"Uninitialized receiver",
303 "Receiver in message expression is an uninitialized value") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000304
Ted Kremenekcf118d42009-02-04 23:49:09 +0000305 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000306 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000307 End = Eng.undef_receivers_end(); I!=End; ++I) {
Mike Stump1eb44332009-09-09 15:08:12 +0000308
Ted Kremenek78d46242008-07-22 16:21:24 +0000309 // Generate a report for this bug.
Ted Kremenek0c313172009-05-13 19:16:35 +0000310 BuiltinBugReport *report = new BuiltinBugReport(*this, desc.c_str(), *I);
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000311 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000312 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
313 const Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
Ted Kremenek78d46242008-07-22 16:21:24 +0000314 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000315 report->addRange(E->getSourceRange());
316 BR.EmitReport(report);
Ted Kremenek0c313172009-05-13 19:16:35 +0000317 }
318 }
Ted Kremenek85ac9342009-05-15 05:25:09 +0000319
Ted Kremenek0c313172009-05-13 19:16:35 +0000320 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000321 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000322 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000323 registerTrackNullOrUndefValue(BRC, GetReceiverExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000324 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000325};
Ted Kremenek5917d782008-11-21 00:27:44 +0000326
Ted Kremenek78d46242008-07-22 16:21:24 +0000327class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
328public:
Ted Kremenek17a8e072009-03-01 05:43:22 +0000329 RetStack(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000330 : BuiltinBug(eng, "Return of address to stack-allocated memory") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000331
Ted Kremenekcf118d42009-02-04 23:49:09 +0000332 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000333 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
334 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000335
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000336 ExplodedNode* N = *I;
Ted Kremenek5f85e172009-07-22 22:35:28 +0000337 const Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
338 const Expr* E = cast<ReturnStmt>(S)->getRetValue();
339 assert(E && "Return expression cannot be NULL");
Mike Stump1eb44332009-09-09 15:08:12 +0000340
Ted Kremenek22bda882008-07-31 20:31:27 +0000341 // Get the value associated with E.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000342 loc::MemRegionVal V = cast<loc::MemRegionVal>(N->getState()->getSVal(E));
Mike Stump1eb44332009-09-09 15:08:12 +0000343
Ted Kremenek22bda882008-07-31 20:31:27 +0000344 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000345 std::string buf;
346 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000347 SourceRange R;
Mike Stump1eb44332009-09-09 15:08:12 +0000348
Ted Kremenek8aed8062008-10-31 00:13:20 +0000349 // Check if the region is a compound literal.
Mike Stump1eb44332009-09-09 15:08:12 +0000350 if (const CompoundLiteralRegion* CR =
Ted Kremenek8aed8062008-10-31 00:13:20 +0000351 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
Mike Stump1eb44332009-09-09 15:08:12 +0000352
Ted Kremenek8aed8062008-10-31 00:13:20 +0000353 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
354 os << "Address of stack memory associated with a compound literal "
355 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000356 << BR.getSourceManager()
357 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000358 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000359
Ted Kremenek8aed8062008-10-31 00:13:20 +0000360 R = CL->getSourceRange();
361 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000362 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
363 const Expr* ARE = AR->getExpr();
364 SourceLocation L = ARE->getLocStart();
365 R = ARE->getSourceRange();
Mike Stump1eb44332009-09-09 15:08:12 +0000366
Ted Kremenekde8cd192008-11-02 00:35:25 +0000367 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000368 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000369 << " returned.";
Mike Stump1eb44332009-09-09 15:08:12 +0000370 }
371 else {
Ted Kremenek8aed8062008-10-31 00:13:20 +0000372 os << "Address of stack memory associated with local variable '"
373 << V.getRegion()->getString() << "' returned.";
374 }
Mike Stump1eb44332009-09-09 15:08:12 +0000375
Ted Kremenekcf118d42009-02-04 23:49:09 +0000376 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
377 report->addRange(E->getSourceRange());
378 if (R.isValid()) report->addRange(R);
379 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000380 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000381 }
382};
Mike Stump1eb44332009-09-09 15:08:12 +0000383
Ted Kremenek5917d782008-11-21 00:27:44 +0000384class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
385public:
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000386 RetUndef(GRExprEngine* eng) : BuiltinBug(eng, "Garbage return value",
387 "Undefined or garbage value returned to caller") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000388
Ted Kremenekcf118d42009-02-04 23:49:09 +0000389 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000390 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
391 }
Mike Stump1eb44332009-09-09 15:08:12 +0000392
Ted Kremenek0c313172009-05-13 19:16:35 +0000393 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000394 const ExplodedNode* N,
Ted Kremenek0c313172009-05-13 19:16:35 +0000395 BuiltinBugReport *R) {
Ted Kremenek85ac9342009-05-15 05:25:09 +0000396 registerTrackNullOrUndefValue(BRC, GetRetValExpr(N), N);
Mike Stump1eb44332009-09-09 15:08:12 +0000397 }
Ted Kremenek5917d782008-11-21 00:27:44 +0000398};
Ted Kremenek78d46242008-07-22 16:21:24 +0000399
400class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
401 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000402 GRStateManager& VM;
403 const GRState* St;
Mike Stump1eb44332009-09-09 15:08:12 +0000404
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000405 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Mike Stump1eb44332009-09-09 15:08:12 +0000406
407 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000408 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000409 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000410
Ted Kremenekb7714b22008-07-30 17:49:12 +0000411 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000412 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
413 Expr* E2 = FindExpr(ExI);
414 if (E2) return E2;
415 }
Mike Stump1eb44332009-09-09 15:08:12 +0000416
Ted Kremenek78d46242008-07-22 16:21:24 +0000417 return Ex;
418 }
Mike Stump1eb44332009-09-09 15:08:12 +0000419
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000420 bool MatchesCriteria(Expr* Ex) { return St->getSVal(Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000421 };
Mike Stump1eb44332009-09-09 15:08:12 +0000422
Ted Kremenek78d46242008-07-22 16:21:24 +0000423public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000424 UndefBranch(GRExprEngine *eng)
Ted Kremenek5b9bd212009-09-11 22:07:28 +0000425 : BuiltinBug(eng,"Use of garbage value",
426 "Branch condition evaluates to an undefined or garbage value")
427 {}
Mike Stump1eb44332009-09-09 15:08:12 +0000428
Ted Kremenekcf118d42009-02-04 23:49:09 +0000429 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000430 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
431 E=Eng.undef_branches_end(); I!=E; ++I) {
432
433 // What's going on here: we want to highlight the subexpression of the
434 // condition that is the most likely source of the "uninitialized
435 // branch condition." We do a recursive walk of the condition's
436 // subexpressions and roughly look for the most nested subexpression
437 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000438 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
439 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
440 assert (Ex && "Block must have a terminator.");
441
442 // Get the predecessor node and check if is a PostStmt with the Stmt
443 // being the terminator condition. We want to inspect the state
444 // of that node instead because it will contain main information about
445 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000446 assert (!(*I)->pred_empty());
447
448 // Note: any predecessor will do. They should have identical state,
449 // since all the BlockEdge did was act as an error sink since the value
450 // had to already be undefined.
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000451 ExplodedNode *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000452 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000453 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000454
455 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
456 if (PS->getStmt() == Ex)
457 St = N->getState();
458
459 FindUndefExpr FindIt(Eng.getStateManager(), St);
460 Ex = FindIt.FindExpr(Ex);
461
Ted Kremenek85ac9342009-05-15 05:25:09 +0000462 ArgReport *R = new ArgReport(*this, desc.c_str(), *I, Ex);
Ted Kremenekcf118d42009-02-04 23:49:09 +0000463 R->addRange(Ex->getSourceRange());
464 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000465 }
466 }
Mike Stump1eb44332009-09-09 15:08:12 +0000467
Ted Kremenek85ac9342009-05-15 05:25:09 +0000468 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000469 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000470 BuiltinBugReport *R) {
471 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
472 N);
473 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000474};
475
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000476class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
477public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000478 OutOfBoundMemoryAccess(GRExprEngine* eng)
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000479 : BuiltinBug(eng,"Out-of-bounds memory access",
Ted Kremenekcf118d42009-02-04 23:49:09 +0000480 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000481
Ted Kremenekcf118d42009-02-04 23:49:09 +0000482 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000483 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
484 }
485};
Mike Stump1eb44332009-09-09 15:08:12 +0000486
Ted Kremenek159d2482008-12-09 00:44:16 +0000487class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000488public:
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000489 BadSizeVLA(GRExprEngine* eng) :
490 BuiltinBug(eng, "Bad variable-length array (VLA) size") {}
Mike Stump1eb44332009-09-09 15:08:12 +0000491
Ted Kremenekcf118d42009-02-04 23:49:09 +0000492 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000493 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000494 I = Eng.ExplicitBadSizedVLA.begin(),
495 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
496
497 // Determine whether this was a 'zero-sized' VLA or a VLA with an
498 // undefined size.
Zhongxing Xu031ccc02009-08-06 12:48:26 +0000499 ExplodedNode* N = *I;
Mike Stump1eb44332009-09-09 15:08:12 +0000500 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenek5f85e172009-07-22 22:35:28 +0000501 const DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
Ted Kremenekefd59942008-12-08 22:47:34 +0000502 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
503 QualType T = Eng.getContext().getCanonicalType(VD->getType());
504 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000505 Expr* SizeExpr = VT->getSizeExpr();
Mike Stump1eb44332009-09-09 15:08:12 +0000506
Ted Kremenek159d2482008-12-09 00:44:16 +0000507 std::string buf;
508 llvm::raw_string_ostream os(buf);
Ted Kremenek5d88ff82009-04-02 02:40:26 +0000509 os << "The expression used to specify the number of elements in the "
510 "variable-length array (VLA) '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000511 << VD->getNameAsString() << "' evaluates to ";
Mike Stump1eb44332009-09-09 15:08:12 +0000512
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000513 bool isUndefined = N->getState()->getSVal(SizeExpr).isUndef();
Mike Stump1eb44332009-09-09 15:08:12 +0000514
Ted Kremenekd49967f2009-04-29 21:58:13 +0000515 if (isUndefined)
Ted Kremenek159d2482008-12-09 00:44:16 +0000516 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000517 else
518 os << "0. VLAs with no elements have undefined behavior.";
Mike Stump1eb44332009-09-09 15:08:12 +0000519
Ted Kremenekd49967f2009-04-29 21:58:13 +0000520 std::string shortBuf;
521 llvm::raw_string_ostream os_short(shortBuf);
522 os_short << "Variable-length array '" << VD->getNameAsString() << "' "
Ted Kremenekeaedfea2009-05-10 05:11:21 +0000523 << (isUndefined ? "garbage value for array size"
524 : "has zero elements (undefined behavior)");
Ted Kremenek159d2482008-12-09 00:44:16 +0000525
Ted Kremenek85ac9342009-05-15 05:25:09 +0000526 ArgReport *report = new ArgReport(*this, os_short.str().c_str(),
527 os.str().c_str(), N, SizeExpr);
528
Ted Kremenekcf118d42009-02-04 23:49:09 +0000529 report->addRange(SizeExpr->getSourceRange());
530 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000531 }
532 }
Mike Stump1eb44332009-09-09 15:08:12 +0000533
Ted Kremenek85ac9342009-05-15 05:25:09 +0000534 void registerInitialVisitors(BugReporterContext& BRC,
Zhongxing Xuc5619d92009-08-06 01:32:16 +0000535 const ExplodedNode* N,
Ted Kremenek85ac9342009-05-15 05:25:09 +0000536 BuiltinBugReport *R) {
537 registerTrackNullOrUndefValue(BRC, static_cast<ArgReport*>(R)->getArg(),
538 N);
539 }
Ted Kremenekefd59942008-12-08 22:47:34 +0000540};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000541
Ted Kremenek78d46242008-07-22 16:21:24 +0000542//===----------------------------------------------------------------------===//
543// __attribute__(nonnull) checking
544
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000545class VISIBILITY_HIDDEN CheckAttrNonNull :
546 public CheckerVisitor<CheckAttrNonNull> {
547
Ted Kremenekcf118d42009-02-04 23:49:09 +0000548 BugType *BT;
Mike Stump1eb44332009-09-09 15:08:12 +0000549
Ted Kremenek78d46242008-07-22 16:21:24 +0000550public:
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000551 CheckAttrNonNull() : BT(0) {}
Ted Kremenek31112182009-07-24 00:40:31 +0000552 ~CheckAttrNonNull() {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000553
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000554 static void *getTag() {
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000555 static int x = 0;
556 return &x;
557 }
558
559 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
560 const GRState *state = C.getState();
561 const GRState *originalState = state;
Mike Stump1eb44332009-09-09 15:08:12 +0000562
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000563 // Check if the callee has a 'nonnull' attribute.
Ted Kremenek23ec48c2009-06-18 23:58:37 +0000564 SVal X = state->getSVal(CE->getCallee());
Mike Stump1eb44332009-09-09 15:08:12 +0000565
Zhongxing Xu369f4472009-04-20 05:24:46 +0000566 const FunctionDecl* FD = X.getAsFunctionDecl();
567 if (!FD)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000568 return;
Zhongxing Xu369f4472009-04-20 05:24:46 +0000569
Mike Stump1eb44332009-09-09 15:08:12 +0000570 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
Ted Kremenek78d46242008-07-22 16:21:24 +0000571 if (!Att)
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000572 return;
Mike Stump1eb44332009-09-09 15:08:12 +0000573
Ted Kremenek78d46242008-07-22 16:21:24 +0000574 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000575 unsigned idx = 0;
Mike Stump1eb44332009-09-09 15:08:12 +0000576
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000577 for (CallExpr::const_arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
Ted Kremenek78d46242008-07-22 16:21:24 +0000578 ++I, ++idx) {
Mike Stump1eb44332009-09-09 15:08:12 +0000579
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000580 if (!Att->isNonNull(idx))
581 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000582
Ted Kremenek08780072009-08-24 22:47:34 +0000583 const SVal &V = state->getSVal(*I);
584 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&V);
Mike Stump1eb44332009-09-09 15:08:12 +0000585
Ted Kremenek08780072009-08-24 22:47:34 +0000586 if (!DV)
587 continue;
Mike Stump1eb44332009-09-09 15:08:12 +0000588
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000589 ConstraintManager &CM = C.getConstraintManager();
590 const GRState *stateNotNull, *stateNull;
Ted Kremenek08780072009-08-24 22:47:34 +0000591 llvm::tie(stateNotNull, stateNull) = CM.AssumeDual(state, *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000592
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000593 if (stateNull && !stateNotNull) {
594 // Generate an error node. Check for a null node in case
595 // we cache out.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000596 if (ExplodedNode *errorNode = C.GenerateNode(CE, stateNull, true)) {
Mike Stump1eb44332009-09-09 15:08:12 +0000597
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000598 // Lazily allocate the BugType object if it hasn't already been
599 // created. Ownership is transferred to the BugReporter object once
600 // the BugReport is passed to 'EmitWarning'.
601 if (!BT)
602 BT = new BugType("Argument with 'nonnull' attribute passed null",
603 "API");
Mike Stump1eb44332009-09-09 15:08:12 +0000604
Ted Kremenek592362b2009-08-18 01:05:30 +0000605 EnhancedBugReport *R =
606 new EnhancedBugReport(*BT,
607 "Null pointer passed as an argument to a "
608 "'nonnull' parameter", errorNode);
Mike Stump1eb44332009-09-09 15:08:12 +0000609
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000610 // Highlight the range of the argument that was null.
Ted Kremenek592362b2009-08-18 01:05:30 +0000611 const Expr *arg = *I;
612 R->addRange(arg->getSourceRange());
613 R->addVisitorCreator(registerTrackNullOrUndefValue, arg);
Mike Stump1eb44332009-09-09 15:08:12 +0000614
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000615 // Emit the bug report.
616 C.EmitReport(R);
617 }
Mike Stump1eb44332009-09-09 15:08:12 +0000618
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000619 // Always return. Either we cached out or we just emitted an error.
620 return;
621 }
Mike Stump1eb44332009-09-09 15:08:12 +0000622
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000623 // If a pointer value passed the check we should assume that it is
624 // indeed not null from this point forward.
625 assert(stateNotNull);
626 state = stateNotNull;
627 }
Mike Stump1eb44332009-09-09 15:08:12 +0000628
Ted Kremenekc26a8b02009-07-22 21:46:56 +0000629 // If we reach here all of the arguments passed the nonnull check.
630 // If 'state' has been updated generated a new node.
631 if (state != originalState)
Zhongxing Xu6403b572009-09-02 13:26:26 +0000632 C.addTransition(C.GenerateNode(CE, state));
Ted Kremenek78d46242008-07-22 16:21:24 +0000633 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000634};
Ted Kremenek78d46242008-07-22 16:21:24 +0000635
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000636// Undefined arguments checking.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000637
Mike Stump1eb44332009-09-09 15:08:12 +0000638class VISIBILITY_HIDDEN CheckUndefinedArg
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000639 : public CheckerVisitor<CheckUndefinedArg> {
640
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000641 BadArg *BT;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000642
643public:
644 CheckUndefinedArg() : BT(0) {}
645 ~CheckUndefinedArg() {}
646
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000647 static void *getTag() {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000648 static int x = 0;
649 return &x;
650 }
651
652 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
653};
654
655void CheckUndefinedArg::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE){
656 for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
657 I != E; ++I) {
658 if (C.getState()->getSVal(*I).isUndef()) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000659 if (ExplodedNode *ErrorNode = C.GenerateNode(CE, true)) {
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000660 if (!BT)
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000661 BT = new BadArg();
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000662 // Generate a report for this bug.
Zhongxing Xu904e1e32009-09-02 07:09:39 +0000663 ArgReport *Report = new ArgReport(*BT, BT->getDescription().c_str(),
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000664 ErrorNode, *I);
665 Report->addRange((*I)->getSourceRange());
666 C.EmitReport(Report);
667 }
668 }
669 }
670}
671
Zhongxing Xud99f3612009-09-02 08:10:35 +0000672class VISIBILITY_HIDDEN CheckBadCall : public CheckerVisitor<CheckBadCall> {
673 BadCall *BT;
674
675public:
676 CheckBadCall() : BT(0) {}
677 ~CheckBadCall() {}
678
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000679 static void *getTag() {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000680 static int x = 0;
681 return &x;
682 }
683
684 void PreVisitCallExpr(CheckerContext &C, const CallExpr *CE);
685};
686
687void CheckBadCall::PreVisitCallExpr(CheckerContext &C, const CallExpr *CE) {
688 const Expr *Callee = CE->getCallee()->IgnoreParens();
689 SVal L = C.getState()->getSVal(Callee);
690
691 if (L.isUndef() || isa<loc::ConcreteInt>(L)) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000692 if (ExplodedNode *N = C.GenerateNode(CE, true)) {
Zhongxing Xud99f3612009-09-02 08:10:35 +0000693 if (!BT)
694 BT = new BadCall();
695 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
696 }
697 }
698}
699
Zhongxing Xu524e4652009-10-22 01:58:10 +0000700class VISIBILITY_HIDDEN CheckDivZero : public CheckerVisitor<CheckDivZero> {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000701 DivZero *BT;
702public:
Zhongxing Xu524e4652009-10-22 01:58:10 +0000703 CheckDivZero() : BT(0) {}
704 ~CheckDivZero() {}
Zhongxing Xu6403b572009-09-02 13:26:26 +0000705
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000706 static void *getTag() {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000707 static int x;
708 return &x;
709 }
710
711 void PreVisitBinaryOperator(CheckerContext &C, const BinaryOperator *B);
712};
713
Zhongxing Xu524e4652009-10-22 01:58:10 +0000714void CheckDivZero::PreVisitBinaryOperator(CheckerContext &C,
715 const BinaryOperator *B) {
Zhongxing Xu6403b572009-09-02 13:26:26 +0000716 BinaryOperator::Opcode Op = B->getOpcode();
717 if (Op != BinaryOperator::Div &&
718 Op != BinaryOperator::Rem &&
719 Op != BinaryOperator::DivAssign &&
720 Op != BinaryOperator::RemAssign)
721 return;
722
723 if (!B->getRHS()->getType()->isIntegerType() ||
724 !B->getRHS()->getType()->isScalarType())
725 return;
726
Zhongxing Xu6403b572009-09-02 13:26:26 +0000727 SVal Denom = C.getState()->getSVal(B->getRHS());
Ted Kremenek970e03a2009-09-03 01:48:03 +0000728 const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom);
729
Ted Kremenek7c039bf2009-09-16 06:04:26 +0000730 // Divide-by-undefined handled in the generic checking for uses of
731 // undefined values.
Mike Stump1eb44332009-09-09 15:08:12 +0000732 if (!DV)
Ted Kremenek970e03a2009-09-03 01:48:03 +0000733 return;
734
Zhongxing Xu6403b572009-09-02 13:26:26 +0000735 // Check for divide by zero.
736 ConstraintManager &CM = C.getConstraintManager();
737 const GRState *stateNotZero, *stateZero;
Ted Kremenek970e03a2009-09-03 01:48:03 +0000738 llvm::tie(stateNotZero, stateZero) = CM.AssumeDual(C.getState(), *DV);
Mike Stump1eb44332009-09-09 15:08:12 +0000739
Zhongxing Xu6403b572009-09-02 13:26:26 +0000740 if (stateZero && !stateNotZero) {
741 if (ExplodedNode *N = C.GenerateNode(B, stateZero, true)) {
742 if (!BT)
743 BT = new DivZero();
Mike Stump1eb44332009-09-09 15:08:12 +0000744
Zhongxing Xu6403b572009-09-02 13:26:26 +0000745 C.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
746 }
747 return;
748 }
749
Zhongxing Xu524e4652009-10-22 01:58:10 +0000750 // If we get here, then the denom should not be zero. We abandon the implicit
751 // zero denom case for now.
Zhongxing Xu6403b572009-09-02 13:26:26 +0000752 if (stateNotZero != C.getState())
753 C.addTransition(C.GenerateNode(B, stateNotZero));
754}
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000755
756class VISIBILITY_HIDDEN CheckUndefDeref : public Checker {
757 UndefinedDeref *BT;
758public:
759 CheckUndefDeref() : BT(0) {}
760
Ted Kremenek3f214b32009-10-29 05:33:39 +0000761 ExplodedNode *CheckLocation(const Stmt *S, ExplodedNode *Pred,
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000762 const GRState *state, SVal V, GRExprEngine &Eng);
763
764 static void *getTag() {
765 static int x = 0;
766 return &x;
767 }
768};
769
Ted Kremenek3f214b32009-10-29 05:33:39 +0000770ExplodedNode *CheckUndefDeref::CheckLocation(const Stmt *S, ExplodedNode *Pred,
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000771 const GRState *state, SVal V,
772 GRExprEngine &Eng) {
773 GRStmtNodeBuilder &Builder = Eng.getBuilder();
774 BugReporter &BR = Eng.getBugReporter();
775
776 if (V.isUndef()) {
777 ExplodedNode *N = Builder.generateNode(S, state, Pred,
778 ProgramPoint::PostUndefLocationCheckFailedKind);
779 if (N) {
780 if (!BT)
781 BT = new UndefinedDeref();
782
783 N->markAsSink();
784 BR.EmitReport(new BuiltinBugReport(*BT, BT->getDescription().c_str(), N));
785 }
786 return 0;
787 }
788
789 return Pred;
Zhongxing Xu9a5bca32009-08-29 02:11:01 +0000790}
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000791
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000792} // end clang namespace
Ted Kremenekbc3a0212009-10-30 17:24:47 +0000793
Ted Kremenek78d46242008-07-22 16:21:24 +0000794//===----------------------------------------------------------------------===//
795// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000796//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000797
798void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000799 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
800 // are different than what probably many checks will do since they don't
801 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
802 // analyzing a function. Generation of BugReport objects is done via a call
803 // to 'FlushReports' from BugReporter.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000804 BR.Register(new UndefBranch(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000805 BR.Register(new UndefResult(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000806 BR.Register(new RetStack(this));
807 BR.Register(new RetUndef(this));
Ted Kremenekcf118d42009-02-04 23:49:09 +0000808 BR.Register(new BadMsgExprArg(this));
809 BR.Register(new BadReceiver(this));
810 BR.Register(new OutOfBoundMemoryAccess(this));
811 BR.Register(new BadSizeVLA(this));
Ted Kremenek21fe8372009-02-19 04:06:22 +0000812 BR.Register(new NilReceiverStructRet(this));
Ted Kremenek899b3de2009-04-08 03:07:17 +0000813 BR.Register(new NilReceiverLargerThanVoidPtrRet(this));
Mike Stump1eb44332009-09-09 15:08:12 +0000814
Ted Kremenekcf118d42009-02-04 23:49:09 +0000815 // The following checks do not need to have their associated BugTypes
816 // explicitly registered with the BugReporter. If they issue any BugReports,
817 // their associated BugType will get registered with the BugReporter
818 // automatically. Note that the check itself is owned by the GRExprEngine
819 // object.
Zhongxing Xuec9227f2009-10-29 02:09:30 +0000820 registerCheck<CheckAttrNonNull>(new CheckAttrNonNull());
821 registerCheck<CheckUndefinedArg>(new CheckUndefinedArg());
822 registerCheck<CheckBadCall>(new CheckBadCall());
823 registerCheck<CheckDivZero>(new CheckDivZero());
824 registerCheck<CheckUndefDeref>(new CheckUndefDeref());
825 registerCheck<NullDerefChecker>(new NullDerefChecker());
Ted Kremenek78d46242008-07-22 16:21:24 +0000826}