blob: c1d6b4d0ebc92b052caf8d1fd14aed13f98eca59 [file] [log] [blame]
George Karpenkov70c2ee32018-08-17 21:41:07 +00001//==--- RetainCountChecker.h - Checks for leaks and other issues -*- 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 methods for RetainCountChecker, which implements
11// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
16#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
17
18#include "../ClangSACheckers.h"
19#include "../AllocationDiagnostics.h"
20#include "../SelectorExtras.h"
21#include "RetainCountSummaries.h"
22#include "RetainCountDiagnostics.h"
23#include "clang/AST/Attr.h"
24#include "clang/AST/DeclCXX.h"
25#include "clang/AST/DeclObjC.h"
26#include "clang/AST/ParentMap.h"
27#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
28#include "clang/Basic/LangOptions.h"
29#include "clang/Basic/SourceManager.h"
30#include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h"
31#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
32#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
33#include "clang/StaticAnalyzer/Core/Checker.h"
34#include "clang/StaticAnalyzer/Core/CheckerManager.h"
35#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
36#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
37#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
38#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
39#include "llvm/ADT/DenseMap.h"
40#include "llvm/ADT/FoldingSet.h"
41#include "llvm/ADT/ImmutableList.h"
42#include "llvm/ADT/ImmutableMap.h"
43#include "llvm/ADT/STLExtras.h"
44#include "llvm/ADT/SmallString.h"
45#include "llvm/ADT/StringExtras.h"
46#include <cstdarg>
47#include <utility>
48
49using namespace objc_retain;
50using llvm::StrInStrNoCase;
51
52namespace clang {
53namespace ento {
54namespace retaincountchecker {
55
56/// Metadata on reference.
57class RefVal {
58public:
59 enum Kind {
60 Owned = 0, // Owning reference.
61 NotOwned, // Reference is not owned by still valid (not freed).
62 Released, // Object has been released.
63 ReturnedOwned, // Returned object passes ownership to caller.
64 ReturnedNotOwned, // Return object does not pass ownership to caller.
65 ERROR_START,
66 ErrorDeallocNotOwned, // -dealloc called on non-owned object.
67 ErrorUseAfterRelease, // Object used after released.
68 ErrorReleaseNotOwned, // Release of an object that was not owned.
69 ERROR_LEAK_START,
70 ErrorLeak, // A memory leak due to excessive reference counts.
71 ErrorLeakReturned, // A memory leak due to the returning method not having
72 // the correct naming conventions.
73 ErrorOverAutorelease,
74 ErrorReturnedNotOwned
75 };
76
77 /// Tracks how an object referenced by an ivar has been used.
78 ///
79 /// This accounts for us not knowing if an arbitrary ivar is supposed to be
80 /// stored at +0 or +1.
81 enum class IvarAccessHistory {
82 None,
83 AccessedDirectly,
84 ReleasedAfterDirectAccess
85 };
86
87private:
88 /// The number of outstanding retains.
89 unsigned Cnt;
90 /// The number of outstanding autoreleases.
91 unsigned ACnt;
92 /// The (static) type of the object at the time we started tracking it.
93 QualType T;
94
95 /// The current state of the object.
96 ///
97 /// See the RefVal::Kind enum for possible values.
98 unsigned RawKind : 5;
99
100 /// The kind of object being tracked (CF or ObjC), if known.
101 ///
102 /// See the RetEffect::ObjKind enum for possible values.
103 unsigned RawObjectKind : 2;
104
105 /// True if the current state and/or retain count may turn out to not be the
106 /// best possible approximation of the reference counting state.
107 ///
108 /// If true, the checker may decide to throw away ("override") this state
109 /// in favor of something else when it sees the object being used in new ways.
110 ///
111 /// This setting should not be propagated to state derived from this state.
112 /// Once we start deriving new states, it would be inconsistent to override
113 /// them.
114 unsigned RawIvarAccessHistory : 2;
115
116 RefVal(Kind k, RetEffect::ObjKind o, unsigned cnt, unsigned acnt, QualType t,
117 IvarAccessHistory IvarAccess)
118 : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
119 RawObjectKind(static_cast<unsigned>(o)),
120 RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
121 assert(getKind() == k && "not enough bits for the kind");
122 assert(getObjKind() == o && "not enough bits for the object kind");
123 assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
124 }
125
126public:
127 Kind getKind() const { return static_cast<Kind>(RawKind); }
128
129 RetEffect::ObjKind getObjKind() const {
130 return static_cast<RetEffect::ObjKind>(RawObjectKind);
131 }
132
133 unsigned getCount() const { return Cnt; }
134 unsigned getAutoreleaseCount() const { return ACnt; }
135 unsigned getCombinedCounts() const { return Cnt + ACnt; }
136 void clearCounts() {
137 Cnt = 0;
138 ACnt = 0;
139 }
140 void setCount(unsigned i) {
141 Cnt = i;
142 }
143 void setAutoreleaseCount(unsigned i) {
144 ACnt = i;
145 }
146
147 QualType getType() const { return T; }
148
149 /// Returns what the analyzer knows about direct accesses to a particular
150 /// instance variable.
151 ///
152 /// If the object with this refcount wasn't originally from an Objective-C
153 /// ivar region, this should always return IvarAccessHistory::None.
154 IvarAccessHistory getIvarAccessHistory() const {
155 return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
156 }
157
158 bool isOwned() const {
159 return getKind() == Owned;
160 }
161
162 bool isNotOwned() const {
163 return getKind() == NotOwned;
164 }
165
166 bool isReturnedOwned() const {
167 return getKind() == ReturnedOwned;
168 }
169
170 bool isReturnedNotOwned() const {
171 return getKind() == ReturnedNotOwned;
172 }
173
174 /// Create a state for an object whose lifetime is the responsibility of the
175 /// current function, at least partially.
176 ///
177 /// Most commonly, this is an owned object with a retain count of +1.
178 static RefVal makeOwned(RetEffect::ObjKind o, QualType t) {
179 return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None);
180 }
181
182 /// Create a state for an object whose lifetime is not the responsibility of
183 /// the current function.
184 ///
185 /// Most commonly, this is an unowned object with a retain count of +0.
186 static RefVal makeNotOwned(RetEffect::ObjKind o, QualType t) {
187 return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None);
188 }
189
190 RefVal operator-(size_t i) const {
191 return RefVal(getKind(), getObjKind(), getCount() - i,
192 getAutoreleaseCount(), getType(), getIvarAccessHistory());
193 }
194
195 RefVal operator+(size_t i) const {
196 return RefVal(getKind(), getObjKind(), getCount() + i,
197 getAutoreleaseCount(), getType(), getIvarAccessHistory());
198 }
199
200 RefVal operator^(Kind k) const {
201 return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
202 getType(), getIvarAccessHistory());
203 }
204
205 RefVal autorelease() const {
206 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
207 getType(), getIvarAccessHistory());
208 }
209
210 RefVal withIvarAccess() const {
211 assert(getIvarAccessHistory() == IvarAccessHistory::None);
212 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
213 getType(), IvarAccessHistory::AccessedDirectly);
214 }
215
216 RefVal releaseViaIvar() const {
217 assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
218 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
219 getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
220 }
221
222 // Comparison, profiling, and pretty-printing.
223
224 bool hasSameState(const RefVal &X) const {
225 return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
226 getIvarAccessHistory() == X.getIvarAccessHistory();
227 }
228
229 bool operator==(const RefVal& X) const {
230 return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
231 }
232
233 void Profile(llvm::FoldingSetNodeID& ID) const {
234 ID.Add(T);
235 ID.AddInteger(RawKind);
236 ID.AddInteger(Cnt);
237 ID.AddInteger(ACnt);
238 ID.AddInteger(RawObjectKind);
239 ID.AddInteger(RawIvarAccessHistory);
240 }
241
242 void print(raw_ostream &Out) const;
243};
244
245class RetainCountChecker
246 : public Checker< check::Bind,
247 check::DeadSymbols,
248 check::EndAnalysis,
249 check::BeginFunction,
250 check::EndFunction,
251 check::PostStmt<BlockExpr>,
252 check::PostStmt<CastExpr>,
253 check::PostStmt<ObjCArrayLiteral>,
254 check::PostStmt<ObjCDictionaryLiteral>,
255 check::PostStmt<ObjCBoxedExpr>,
256 check::PostStmt<ObjCIvarRefExpr>,
257 check::PostCall,
258 check::PreStmt<ReturnStmt>,
259 check::RegionChanges,
260 eval::Assume,
261 eval::Call > {
262 mutable std::unique_ptr<CFRefBug> useAfterRelease, releaseNotOwned;
263 mutable std::unique_ptr<CFRefBug> deallocNotOwned;
264 mutable std::unique_ptr<CFRefBug> overAutorelease, returnNotOwnedForOwned;
265 mutable std::unique_ptr<CFRefBug> leakWithinFunction, leakAtReturn;
266
267 typedef llvm::DenseMap<SymbolRef, const CheckerProgramPointTag *> SymbolTagMap;
268
269 // This map is only used to ensure proper deletion of any allocated tags.
270 mutable SymbolTagMap DeadSymbolTags;
271
272 mutable std::unique_ptr<RetainSummaryManager> Summaries;
273 mutable SummaryLogTy SummaryLog;
274 mutable bool ShouldResetSummaryLog;
275
276 /// Optional setting to indicate if leak reports should include
277 /// the allocation line.
278 mutable bool IncludeAllocationLine;
279
280public:
281 RetainCountChecker(AnalyzerOptions &AO)
282 : ShouldResetSummaryLog(false),
283 IncludeAllocationLine(shouldIncludeAllocationSiteInLeakDiagnostics(AO)) {}
284
285 ~RetainCountChecker() override { DeleteContainerSeconds(DeadSymbolTags); }
286
287 void checkEndAnalysis(ExplodedGraph &G, BugReporter &BR,
288 ExprEngine &Eng) const {
289 // FIXME: This is a hack to make sure the summary log gets cleared between
290 // analyses of different code bodies.
291 //
292 // Why is this necessary? Because a checker's lifetime is tied to a
293 // translation unit, but an ExplodedGraph's lifetime is just a code body.
294 // Once in a blue moon, a new ExplodedNode will have the same address as an
295 // old one with an associated summary, and the bug report visitor gets very
296 // confused. (To make things worse, the summary lifetime is currently also
297 // tied to a code body, so we get a crash instead of incorrect results.)
298 //
299 // Why is this a bad solution? Because if the lifetime of the ExplodedGraph
300 // changes, things will start going wrong again. Really the lifetime of this
301 // log needs to be tied to either the specific nodes in it or the entire
302 // ExplodedGraph, not to a specific part of the code being analyzed.
303 //
304 // (Also, having stateful local data means that the same checker can't be
305 // used from multiple threads, but a lot of checkers have incorrect
306 // assumptions about that anyway. So that wasn't a priority at the time of
307 // this fix.)
308 //
309 // This happens at the end of analysis, but bug reports are emitted /after/
310 // this point. So we can't just clear the summary log now. Instead, we mark
311 // that the next time we access the summary log, it should be cleared.
312
313 // If we never reset the summary log during /this/ code body analysis,
314 // there were no new summaries. There might still have been summaries from
315 // the /last/ analysis, so clear them out to make sure the bug report
316 // visitors don't get confused.
317 if (ShouldResetSummaryLog)
318 SummaryLog.clear();
319
320 ShouldResetSummaryLog = !SummaryLog.empty();
321 }
322
323 CFRefBug *getLeakWithinFunctionBug(const LangOptions &LOpts) const {
324 if (!leakWithinFunction)
325 leakWithinFunction.reset(new Leak(this, "Leak"));
326 return leakWithinFunction.get();
327 }
328
329 CFRefBug *getLeakAtReturnBug(const LangOptions &LOpts) const {
330 if (!leakAtReturn)
331 leakAtReturn.reset(new Leak(this, "Leak of returned object"));
332 return leakAtReturn.get();
333 }
334
335 RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
336 // FIXME: We don't support ARC being turned on and off during one analysis.
337 // (nor, for that matter, do we support changing ASTContexts)
338 bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
339 if (!Summaries)
340 Summaries.reset(new RetainSummaryManager(Ctx, ARCEnabled));
341 else
342 assert(Summaries->isARCEnabled() == ARCEnabled);
343 return *Summaries;
344 }
345
346 RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
347 return getSummaryManager(C.getASTContext());
348 }
349
350 void printState(raw_ostream &Out, ProgramStateRef State,
351 const char *NL, const char *Sep) const override;
352
353 void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
354 void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
355 void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
356
357 void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
358 void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
359 void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
360
361 void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
362
363 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
364
365 void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
366 CheckerContext &C) const;
367
368 void processSummaryOfInlined(const RetainSummary &Summ,
369 const CallEvent &Call,
370 CheckerContext &C) const;
371
372 bool evalCall(const CallExpr *CE, CheckerContext &C) const;
373
374 ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
375 bool Assumption) const;
376
377 ProgramStateRef
378 checkRegionChanges(ProgramStateRef state,
379 const InvalidatedSymbols *invalidated,
380 ArrayRef<const MemRegion *> ExplicitRegions,
381 ArrayRef<const MemRegion *> Regions,
382 const LocationContext* LCtx,
383 const CallEvent *Call) const;
384
385 void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
386 void checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
387 ExplodedNode *Pred, RetEffect RE, RefVal X,
388 SymbolRef Sym, ProgramStateRef state) const;
389
390 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
391 void checkBeginFunction(CheckerContext &C) const;
392 void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
393
394 ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
395 RefVal V, ArgEffect E, RefVal::Kind &hasErr,
396 CheckerContext &C) const;
397
398 void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
399 RefVal::Kind ErrorKind, SymbolRef Sym,
400 CheckerContext &C) const;
401
402 void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
403
404 const ProgramPointTag *getDeadSymbolTag(SymbolRef sym) const;
405
406 ProgramStateRef handleSymbolDeath(ProgramStateRef state,
407 SymbolRef sid, RefVal V,
408 SmallVectorImpl<SymbolRef> &Leaked) const;
409
410 ProgramStateRef
411 handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
412 const ProgramPointTag *Tag, CheckerContext &Ctx,
413 SymbolRef Sym, RefVal V) const;
414
415 ExplodedNode *processLeaks(ProgramStateRef state,
416 SmallVectorImpl<SymbolRef> &Leaked,
417 CheckerContext &Ctx,
418 ExplodedNode *Pred = nullptr) const;
419};
420
421//===----------------------------------------------------------------------===//
422// RefBindings - State used to track object reference counts.
423//===----------------------------------------------------------------------===//
424
425const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
426
427ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym,
428 RefVal Val);
429
430ProgramStateRef removeRefBinding(ProgramStateRef State, SymbolRef Sym);
431
432/// Returns true if this stack frame is for an Objective-C method that is a
433/// property getter or setter whose body has been synthesized by the analyzer.
434inline bool isSynthesizedAccessor(const StackFrameContext *SFC) {
435 auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
436 if (!Method || !Method->isPropertyAccessor())
437 return false;
438
439 return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
440}
441
442} // end namespace retaincountchecker
443} // end namespace ento
444} // end namespace clang
445
446#endif