blob: 76286f4dbf27b70b9f8b34ca1bdab51c4aa50884 [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 Kremenek8aed8062008-10-31 00:13:20 +000017#include "clang/Basic/SourceManager.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000018#include "llvm/Support/Compiler.h"
Ted Kremenekad51a602008-10-31 00:18:30 +000019#include "llvm/Support/raw_ostream.h"
Ted Kremenek78d46242008-07-22 16:21:24 +000020
21using namespace clang;
22
23//===----------------------------------------------------------------------===//
24// Utility functions.
25//===----------------------------------------------------------------------===//
26
27template <typename ITERATOR> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000028ExplodedNode<GRState>* GetNode(ITERATOR I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000029 return *I;
30}
31
32template <> inline
Ted Kremenek4adc81e2008-08-13 04:27:00 +000033ExplodedNode<GRState>* GetNode(GRExprEngine::undef_arg_iterator I) {
Ted Kremenek78d46242008-07-22 16:21:24 +000034 return I->first;
35}
36
37//===----------------------------------------------------------------------===//
38// Bug Descriptions.
39//===----------------------------------------------------------------------===//
40
41namespace {
Ted Kremenekcf118d42009-02-04 23:49:09 +000042class VISIBILITY_HIDDEN BuiltinBug : public BugType {
43 GRExprEngine &Eng;
Ted Kremenek159d2482008-12-09 00:44:16 +000044protected:
Ted Kremenekcf118d42009-02-04 23:49:09 +000045 const std::string desc;
Ted Kremenek78d46242008-07-22 16:21:24 +000046public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000047 BuiltinBug(GRExprEngine *eng, const char* n, const char* d)
48 : BugType(n, "Logic Errors"), Eng(*eng), desc(d) {}
49
50 BuiltinBug(GRExprEngine *eng, const char* n)
51 : BugType(n, "Logic Errors"), Eng(*eng), desc(n) {}
Ted Kremenek22bda882008-07-31 20:31:27 +000052
Ted Kremenekcf118d42009-02-04 23:49:09 +000053 virtual void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) = 0;
54
55 void FlushReports(BugReporter& BR) { FlushReportsImpl(BR, Eng); }
Ted Kremenek78d46242008-07-22 16:21:24 +000056
57 template <typename ITER>
58 void Emit(BugReporter& BR, ITER I, ITER E) {
Ted Kremenekcf118d42009-02-04 23:49:09 +000059 for (; I != E; ++I) BR.EmitReport(new BugReport(*this, desc.c_str(),
60 GetNode(I)));
61 }
Ted Kremenek78d46242008-07-22 16:21:24 +000062};
63
64class VISIBILITY_HIDDEN NullDeref : public BuiltinBug {
65public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000066 NullDeref(GRExprEngine* eng)
67 : BuiltinBug(eng,"null dereference", "Dereference of null pointer.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +000068
Ted Kremenekcf118d42009-02-04 23:49:09 +000069 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +000070 Emit(BR, Eng.null_derefs_begin(), Eng.null_derefs_end());
71 }
72};
73
74class VISIBILITY_HIDDEN UndefinedDeref : public BuiltinBug {
75public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000076 UndefinedDeref(GRExprEngine* eng)
77 : BuiltinBug(eng,"uninitialized pointer dereference",
78 "Dereference of undefined value.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +000079
Ted Kremenekcf118d42009-02-04 23:49:09 +000080 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +000081 Emit(BR, Eng.undef_derefs_begin(), Eng.undef_derefs_end());
82 }
83};
84
85class VISIBILITY_HIDDEN DivZero : public BuiltinBug {
86public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000087 DivZero(GRExprEngine* eng)
88 : BuiltinBug(eng,"divide-by-zero", "Division by zero/undefined value.") {}
Ted Kremenek78d46242008-07-22 16:21:24 +000089
Ted Kremenekcf118d42009-02-04 23:49:09 +000090 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +000091 Emit(BR, Eng.explicit_bad_divides_begin(), Eng.explicit_bad_divides_end());
92 }
93};
94
95class VISIBILITY_HIDDEN UndefResult : public BuiltinBug {
96public:
Ted Kremenekcf118d42009-02-04 23:49:09 +000097 UndefResult(GRExprEngine* eng) : BuiltinBug(eng,"undefined result",
Ted Kremenek78d46242008-07-22 16:21:24 +000098 "Result of operation is undefined.") {}
99
Ted Kremenekcf118d42009-02-04 23:49:09 +0000100 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000101 Emit(BR, Eng.undef_results_begin(), Eng.undef_results_end());
102 }
103};
104
105class VISIBILITY_HIDDEN BadCall : public BuiltinBug {
106public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000107 BadCall(GRExprEngine *eng)
108 : BuiltinBug(eng,"invalid function call",
Ted Kremenek78d46242008-07-22 16:21:24 +0000109 "Called function is a NULL or undefined function pointer value.") {}
110
Ted Kremenekcf118d42009-02-04 23:49:09 +0000111 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000112 Emit(BR, Eng.bad_calls_begin(), Eng.bad_calls_end());
113 }
114};
115
116class VISIBILITY_HIDDEN BadArg : public BuiltinBug {
117public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000118 BadArg(GRExprEngine* eng) : BuiltinBug(eng,"uninitialized argument",
Ted Kremenek78d46242008-07-22 16:21:24 +0000119 "Pass-by-value argument in function is undefined.") {}
120
Ted Kremenekcf118d42009-02-04 23:49:09 +0000121 BadArg(GRExprEngine* eng, const char* d)
122 : BuiltinBug(eng,"uninitialized argument", d) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000123
Ted Kremenekcf118d42009-02-04 23:49:09 +0000124 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000125 for (GRExprEngine::UndefArgsTy::iterator I = Eng.undef_arg_begin(),
126 E = Eng.undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000127 // Generate a report for this bug.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000128 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(),
129 I->first);
130 report->addRange(I->second->getSourceRange());
131 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000132 }
133 }
134};
135
136class VISIBILITY_HIDDEN BadMsgExprArg : public BadArg {
137public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000138 BadMsgExprArg(GRExprEngine* eng)
139 : BadArg(eng,"Pass-by-value argument in message expression is undefined."){}
Ted Kremenek78d46242008-07-22 16:21:24 +0000140
Ted Kremenekcf118d42009-02-04 23:49:09 +0000141 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000142 for (GRExprEngine::UndefArgsTy::iterator I=Eng.msg_expr_undef_arg_begin(),
Ted Kremenekcf118d42009-02-04 23:49:09 +0000143 E = Eng.msg_expr_undef_arg_end(); I!=E; ++I) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000144 // Generate a report for this bug.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000145 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(), I->first);
146 report->addRange(I->second->getSourceRange());
147 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000148 }
149 }
150};
151
152class VISIBILITY_HIDDEN BadReceiver : public BuiltinBug {
153public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000154 BadReceiver(GRExprEngine* eng)
155 : BuiltinBug(eng,"uninitialized receiver",
Ted Kremenek78d46242008-07-22 16:21:24 +0000156 "Receiver in message expression is an uninitialized value.") {}
157
Ted Kremenekcf118d42009-02-04 23:49:09 +0000158 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000159 for (GRExprEngine::ErrorNodes::iterator I=Eng.undef_receivers_begin(),
Ted Kremenek78d46242008-07-22 16:21:24 +0000160 End = Eng.undef_receivers_end(); I!=End; ++I) {
161
162 // Generate a report for this bug.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000163 RangedBugReport *report = new RangedBugReport(*this, desc.c_str(), *I);
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000164 ExplodedNode<GRState>* N = *I;
Ted Kremenek78d46242008-07-22 16:21:24 +0000165 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
166 Expr* E = cast<ObjCMessageExpr>(S)->getReceiver();
167 assert (E && "Receiver cannot be NULL");
Ted Kremenekcf118d42009-02-04 23:49:09 +0000168 report->addRange(E->getSourceRange());
169 BR.EmitReport(report);
Ted Kremenek78d46242008-07-22 16:21:24 +0000170 }
171 }
172};
Ted Kremenek5917d782008-11-21 00:27:44 +0000173
Ted Kremenek78d46242008-07-22 16:21:24 +0000174class VISIBILITY_HIDDEN RetStack : public BuiltinBug {
175public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000176 RetStack(GRExprEngine* eng) : BuiltinBug(eng, "return of stack address") {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000177
Ted Kremenekcf118d42009-02-04 23:49:09 +0000178 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekb7714b22008-07-30 17:49:12 +0000179 for (GRExprEngine::ret_stackaddr_iterator I=Eng.ret_stackaddr_begin(),
180 End = Eng.ret_stackaddr_end(); I!=End; ++I) {
Ted Kremenek22bda882008-07-31 20:31:27 +0000181
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000182 ExplodedNode<GRState>* N = *I;
Ted Kremenekb7714b22008-07-30 17:49:12 +0000183 Stmt *S = cast<PostStmt>(N->getLocation()).getStmt();
184 Expr* E = cast<ReturnStmt>(S)->getRetValue();
185 assert (E && "Return expression cannot be NULL");
Ted Kremenek22bda882008-07-31 20:31:27 +0000186
187 // Get the value associated with E.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000188 loc::MemRegionVal V =
189 cast<loc::MemRegionVal>(Eng.getStateManager().GetSVal(N->getState(),
Ted Kremenek9e240492008-10-04 05:50:14 +0000190 E));
Ted Kremenek22bda882008-07-31 20:31:27 +0000191
192 // Generate a report for this bug.
Ted Kremenekad51a602008-10-31 00:18:30 +0000193 std::string buf;
194 llvm::raw_string_ostream os(buf);
Ted Kremenek8aed8062008-10-31 00:13:20 +0000195 SourceRange R;
Ted Kremenek22bda882008-07-31 20:31:27 +0000196
Ted Kremenek8aed8062008-10-31 00:13:20 +0000197 // Check if the region is a compound literal.
198 if (const CompoundLiteralRegion* CR =
199 dyn_cast<CompoundLiteralRegion>(V.getRegion())) {
200
201 const CompoundLiteralExpr* CL = CR->getLiteralExpr();
202 os << "Address of stack memory associated with a compound literal "
203 "declared on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000204 << BR.getSourceManager()
205 .getInstantiationLineNumber(CL->getLocStart())
Ted Kremenek8aed8062008-10-31 00:13:20 +0000206 << " returned.";
207
208 R = CL->getSourceRange();
209 }
Ted Kremenekde8cd192008-11-02 00:35:25 +0000210 else if (const AllocaRegion* AR = dyn_cast<AllocaRegion>(V.getRegion())) {
211 const Expr* ARE = AR->getExpr();
212 SourceLocation L = ARE->getLocStart();
213 R = ARE->getSourceRange();
214
215 os << "Address of stack memory allocated by call to alloca() on line "
Chris Lattnerf7cf85b2009-01-16 07:36:28 +0000216 << BR.getSourceManager().getInstantiationLineNumber(L)
Ted Kremenekde8cd192008-11-02 00:35:25 +0000217 << " returned.";
218 }
Ted Kremenek8aed8062008-10-31 00:13:20 +0000219 else {
220 os << "Address of stack memory associated with local variable '"
221 << V.getRegion()->getString() << "' returned.";
222 }
Ted Kremenek22bda882008-07-31 20:31:27 +0000223
Ted Kremenekcf118d42009-02-04 23:49:09 +0000224 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
225 report->addRange(E->getSourceRange());
226 if (R.isValid()) report->addRange(R);
227 BR.EmitReport(report);
Ted Kremenekb7714b22008-07-30 17:49:12 +0000228 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000229 }
230};
Ted Kremenek5917d782008-11-21 00:27:44 +0000231
232class VISIBILITY_HIDDEN RetUndef : public BuiltinBug {
233public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000234 RetUndef(GRExprEngine* eng) : BuiltinBug(eng,"uninitialized return value",
Ted Kremenek5917d782008-11-21 00:27:44 +0000235 "Uninitialized or undefined return value returned to caller.") {}
236
Ted Kremenekcf118d42009-02-04 23:49:09 +0000237 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek5917d782008-11-21 00:27:44 +0000238 Emit(BR, Eng.ret_undef_begin(), Eng.ret_undef_end());
239 }
240};
Ted Kremenek78d46242008-07-22 16:21:24 +0000241
242class VISIBILITY_HIDDEN UndefBranch : public BuiltinBug {
243 struct VISIBILITY_HIDDEN FindUndefExpr {
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000244 GRStateManager& VM;
245 const GRState* St;
Ted Kremenek78d46242008-07-22 16:21:24 +0000246
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000247 FindUndefExpr(GRStateManager& V, const GRState* S) : VM(V), St(S) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000248
Ted Kremenekb7714b22008-07-30 17:49:12 +0000249 Expr* FindExpr(Expr* Ex) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000250 if (!MatchesCriteria(Ex))
Ted Kremenekb7714b22008-07-30 17:49:12 +0000251 return 0;
Ted Kremenek78d46242008-07-22 16:21:24 +0000252
Ted Kremenekb7714b22008-07-30 17:49:12 +0000253 for (Stmt::child_iterator I=Ex->child_begin(), E=Ex->child_end();I!=E;++I)
Ted Kremenek78d46242008-07-22 16:21:24 +0000254 if (Expr* ExI = dyn_cast_or_null<Expr>(*I)) {
255 Expr* E2 = FindExpr(ExI);
256 if (E2) return E2;
257 }
258
259 return Ex;
260 }
261
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000262 bool MatchesCriteria(Expr* Ex) { return VM.GetSVal(St, Ex).isUndef(); }
Ted Kremenek78d46242008-07-22 16:21:24 +0000263 };
264
265public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000266 UndefBranch(GRExprEngine *eng)
267 : BuiltinBug(eng,"uninitialized value",
Ted Kremenek78d46242008-07-22 16:21:24 +0000268 "Branch condition evaluates to an uninitialized value.") {}
269
Ted Kremenekcf118d42009-02-04 23:49:09 +0000270 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000271 for (GRExprEngine::undef_branch_iterator I=Eng.undef_branches_begin(),
272 E=Eng.undef_branches_end(); I!=E; ++I) {
273
274 // What's going on here: we want to highlight the subexpression of the
275 // condition that is the most likely source of the "uninitialized
276 // branch condition." We do a recursive walk of the condition's
277 // subexpressions and roughly look for the most nested subexpression
278 // that binds to Undefined. We then highlight that expression's range.
Ted Kremenek78d46242008-07-22 16:21:24 +0000279 BlockEdge B = cast<BlockEdge>((*I)->getLocation());
280 Expr* Ex = cast<Expr>(B.getSrc()->getTerminatorCondition());
281 assert (Ex && "Block must have a terminator.");
282
283 // Get the predecessor node and check if is a PostStmt with the Stmt
284 // being the terminator condition. We want to inspect the state
285 // of that node instead because it will contain main information about
286 // the subexpressions.
Ted Kremenek78d46242008-07-22 16:21:24 +0000287 assert (!(*I)->pred_empty());
288
289 // Note: any predecessor will do. They should have identical state,
290 // since all the BlockEdge did was act as an error sink since the value
291 // had to already be undefined.
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000292 ExplodedNode<GRState> *N = *(*I)->pred_begin();
Ted Kremenek78d46242008-07-22 16:21:24 +0000293 ProgramPoint P = N->getLocation();
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000294 const GRState* St = (*I)->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000295
296 if (PostStmt* PS = dyn_cast<PostStmt>(&P))
297 if (PS->getStmt() == Ex)
298 St = N->getState();
299
300 FindUndefExpr FindIt(Eng.getStateManager(), St);
301 Ex = FindIt.FindExpr(Ex);
302
Ted Kremenekcf118d42009-02-04 23:49:09 +0000303 RangedBugReport *R = new RangedBugReport(*this, desc.c_str(), *I);
304 R->addRange(Ex->getSourceRange());
305 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000306 }
307 }
308};
309
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000310class VISIBILITY_HIDDEN OutOfBoundMemoryAccess : public BuiltinBug {
311public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000312 OutOfBoundMemoryAccess(GRExprEngine* eng)
313 : BuiltinBug(eng,"out-of-bound memory access",
314 "Load or store into an out-of-bound memory position.") {}
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000315
Ted Kremenekcf118d42009-02-04 23:49:09 +0000316 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000317 Emit(BR, Eng.explicit_oob_memacc_begin(), Eng.explicit_oob_memacc_end());
318 }
319};
Ted Kremenekefd59942008-12-08 22:47:34 +0000320
Ted Kremenek159d2482008-12-09 00:44:16 +0000321class VISIBILITY_HIDDEN BadSizeVLA : public BuiltinBug {
Ted Kremenekefd59942008-12-08 22:47:34 +0000322public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000323 BadSizeVLA(GRExprEngine* eng) : BuiltinBug(eng, "bad VLA size") {}
Ted Kremenekefd59942008-12-08 22:47:34 +0000324
Ted Kremenekcf118d42009-02-04 23:49:09 +0000325 void FlushReportsImpl(BugReporter& BR, GRExprEngine& Eng) {
Ted Kremenekefd59942008-12-08 22:47:34 +0000326 for (GRExprEngine::ErrorNodes::iterator
Ted Kremenek159d2482008-12-09 00:44:16 +0000327 I = Eng.ExplicitBadSizedVLA.begin(),
328 E = Eng.ExplicitBadSizedVLA.end(); I!=E; ++I) {
329
330 // Determine whether this was a 'zero-sized' VLA or a VLA with an
331 // undefined size.
332 GRExprEngine::NodeTy* N = *I;
333 PostStmt PS = cast<PostStmt>(N->getLocation());
Ted Kremenekefd59942008-12-08 22:47:34 +0000334 DeclStmt *DS = cast<DeclStmt>(PS.getStmt());
335 VarDecl* VD = cast<VarDecl>(*DS->decl_begin());
336 QualType T = Eng.getContext().getCanonicalType(VD->getType());
337 VariableArrayType* VT = cast<VariableArrayType>(T);
Ted Kremenek159d2482008-12-09 00:44:16 +0000338 Expr* SizeExpr = VT->getSizeExpr();
Ted Kremenekefd59942008-12-08 22:47:34 +0000339
Ted Kremenek159d2482008-12-09 00:44:16 +0000340 std::string buf;
341 llvm::raw_string_ostream os(buf);
342 os << "The expression used to specify the number of elements in the VLA '"
Ted Kremenekcf118d42009-02-04 23:49:09 +0000343 << VD->getNameAsString() << "' evaluates to ";
Ted Kremenek159d2482008-12-09 00:44:16 +0000344
Ted Kremenekcf118d42009-02-04 23:49:09 +0000345 if (Eng.getStateManager().GetSVal(N->getState(), SizeExpr).isUndef())
Ted Kremenek159d2482008-12-09 00:44:16 +0000346 os << "an undefined or garbage value.";
Ted Kremenekcf118d42009-02-04 23:49:09 +0000347 else
348 os << "0. VLAs with no elements have undefined behavior.";
Ted Kremenek159d2482008-12-09 00:44:16 +0000349
Ted Kremenekcf118d42009-02-04 23:49:09 +0000350 RangedBugReport *report = new RangedBugReport(*this, os.str().c_str(), N);
351 report->addRange(SizeExpr->getSourceRange());
352 BR.EmitReport(report);
Ted Kremenekefd59942008-12-08 22:47:34 +0000353 }
354 }
355};
Zhongxing Xu1c0c2332008-11-23 05:52:28 +0000356
Ted Kremenek78d46242008-07-22 16:21:24 +0000357//===----------------------------------------------------------------------===//
358// __attribute__(nonnull) checking
359
360class VISIBILITY_HIDDEN CheckAttrNonNull : public GRSimpleAPICheck {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000361 BugType *BT;
362 BugReporter &BR;
Ted Kremenek78d46242008-07-22 16:21:24 +0000363
364public:
Ted Kremenekcf118d42009-02-04 23:49:09 +0000365 CheckAttrNonNull(BugReporter &br) : BT(0), BR(br) {}
Ted Kremenek78d46242008-07-22 16:21:24 +0000366
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000367 virtual bool Audit(ExplodedNode<GRState>* N, GRStateManager& VMgr) {
Ted Kremenek78d46242008-07-22 16:21:24 +0000368 CallExpr* CE = cast<CallExpr>(cast<PostStmt>(N->getLocation()).getStmt());
Ted Kremenek4adc81e2008-08-13 04:27:00 +0000369 const GRState* state = N->getState();
Ted Kremenek78d46242008-07-22 16:21:24 +0000370
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000371 SVal X = VMgr.GetSVal(state, CE->getCallee());
Ted Kremenek78d46242008-07-22 16:21:24 +0000372
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000373 if (!isa<loc::FuncVal>(X))
Ted Kremenek78d46242008-07-22 16:21:24 +0000374 return false;
375
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000376 FunctionDecl* FD = dyn_cast<FunctionDecl>(cast<loc::FuncVal>(X).getDecl());
Ted Kremenek78d46242008-07-22 16:21:24 +0000377 const NonNullAttr* Att = FD->getAttr<NonNullAttr>();
378
379 if (!Att)
380 return false;
381
382 // Iterate through the arguments of CE and check them for null.
Ted Kremenek78d46242008-07-22 16:21:24 +0000383 unsigned idx = 0;
384 bool hasError = false;
385
386 for (CallExpr::arg_iterator I=CE->arg_begin(), E=CE->arg_end(); I!=E;
387 ++I, ++idx) {
388
389 if (!VMgr.isEqual(state, *I, 0) || !Att->isNonNull(idx))
390 continue;
Ted Kremenekcf118d42009-02-04 23:49:09 +0000391
392 // Lazily allocate the BugType object if it hasn't already been created.
393 // Ownership is transferred to the BugReporter object once the BugReport
394 // is passed to 'EmitWarning'.
395 if (!BT) BT = new BugType("'nonnull' argument passed null", "API");
Ted Kremenek78d46242008-07-22 16:21:24 +0000396
Ted Kremenekcf118d42009-02-04 23:49:09 +0000397 RangedBugReport *R = new RangedBugReport(*BT,
398 "Null pointer passed as an argument to a "
399 "'nonnull' parameter", N);
400
401 R->addRange((*I)->getSourceRange());
402 BR.EmitReport(R);
Ted Kremenek78d46242008-07-22 16:21:24 +0000403 hasError = true;
404 }
405
406 return hasError;
407 }
Ted Kremenek78d46242008-07-22 16:21:24 +0000408};
409} // end anonymous namespace
410
411//===----------------------------------------------------------------------===//
412// Check registration.
Ted Kremenekcf118d42009-02-04 23:49:09 +0000413//===----------------------------------------------------------------------===//
Ted Kremenek78d46242008-07-22 16:21:24 +0000414
415void GRExprEngine::RegisterInternalChecks() {
Ted Kremenekcf118d42009-02-04 23:49:09 +0000416 // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
417 // are different than what probably many checks will do since they don't
418 // create BugReports on-the-fly but instead wait until GRExprEngine finishes
419 // analyzing a function. Generation of BugReport objects is done via a call
420 // to 'FlushReports' from BugReporter.
421 BR.Register(new NullDeref(this));
422 BR.Register(new UndefinedDeref(this));
423 BR.Register(new UndefBranch(this));
424 BR.Register(new DivZero(this));
425 BR.Register(new UndefResult(this));
426 BR.Register(new BadCall(this));
427 BR.Register(new RetStack(this));
428 BR.Register(new RetUndef(this));
429 BR.Register(new BadArg(this));
430 BR.Register(new BadMsgExprArg(this));
431 BR.Register(new BadReceiver(this));
432 BR.Register(new OutOfBoundMemoryAccess(this));
433 BR.Register(new BadSizeVLA(this));
434
435 // The following checks do not need to have their associated BugTypes
436 // explicitly registered with the BugReporter. If they issue any BugReports,
437 // their associated BugType will get registered with the BugReporter
438 // automatically. Note that the check itself is owned by the GRExprEngine
439 // object.
440 AddCheck(new CheckAttrNonNull(BR), Stmt::CallExprClass);
Ted Kremenek78d46242008-07-22 16:21:24 +0000441}