blob: 506ece1e57858a709e40c662a28a83d255501236 [file] [log] [blame]
George Karpenkov70c2ee32018-08-17 21:41:07 +00001//==--- RetainCountChecker.h - Checks for leaks and other issues -*- C++ -*--//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
George Karpenkov70c2ee32018-08-17 21:41:07 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file defines the methods for RetainCountChecker, which implements
10// a reference count checker for Core Foundation and Cocoa on (Mac OS X).
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
15#define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_H
16
Kristof Umann76a21502018-12-15 16:23:51 +000017#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
George Karpenkov70c2ee32018-08-17 21:41:07 +000018#include "RetainCountDiagnostics.h"
19#include "clang/AST/Attr.h"
20#include "clang/AST/DeclCXX.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/ParentMap.h"
23#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
George Karpenkov6fdd2bd2019-01-25 01:24:04 +000024#include "clang/Analysis/RetainSummaryManager.h"
George Karpenkov70c2ee32018-08-17 21:41:07 +000025#include "clang/Basic/LangOptions.h"
26#include "clang/Basic/SourceManager.h"
George Karpenkovefef49c2018-08-21 03:09:02 +000027#include "clang/Analysis/SelectorExtras.h"
George Karpenkov70c2ee32018-08-17 21:41:07 +000028#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
29#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
30#include "clang/StaticAnalyzer/Core/Checker.h"
31#include "clang/StaticAnalyzer/Core/CheckerManager.h"
32#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
33#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
34#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
35#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
36#include "llvm/ADT/DenseMap.h"
37#include "llvm/ADT/FoldingSet.h"
38#include "llvm/ADT/ImmutableList.h"
39#include "llvm/ADT/ImmutableMap.h"
40#include "llvm/ADT/STLExtras.h"
41#include "llvm/ADT/SmallString.h"
42#include "llvm/ADT/StringExtras.h"
43#include <cstdarg>
44#include <utility>
45
George Karpenkov70c2ee32018-08-17 21:41:07 +000046namespace clang {
47namespace ento {
48namespace retaincountchecker {
49
50/// Metadata on reference.
51class RefVal {
52public:
53 enum Kind {
54 Owned = 0, // Owning reference.
55 NotOwned, // Reference is not owned by still valid (not freed).
56 Released, // Object has been released.
57 ReturnedOwned, // Returned object passes ownership to caller.
58 ReturnedNotOwned, // Return object does not pass ownership to caller.
59 ERROR_START,
60 ErrorDeallocNotOwned, // -dealloc called on non-owned object.
61 ErrorUseAfterRelease, // Object used after released.
62 ErrorReleaseNotOwned, // Release of an object that was not owned.
63 ERROR_LEAK_START,
64 ErrorLeak, // A memory leak due to excessive reference counts.
65 ErrorLeakReturned, // A memory leak due to the returning method not having
66 // the correct naming conventions.
67 ErrorOverAutorelease,
68 ErrorReturnedNotOwned
69 };
70
71 /// Tracks how an object referenced by an ivar has been used.
72 ///
73 /// This accounts for us not knowing if an arbitrary ivar is supposed to be
74 /// stored at +0 or +1.
75 enum class IvarAccessHistory {
76 None,
77 AccessedDirectly,
78 ReleasedAfterDirectAccess
79 };
80
81private:
82 /// The number of outstanding retains.
83 unsigned Cnt;
84 /// The number of outstanding autoreleases.
85 unsigned ACnt;
86 /// The (static) type of the object at the time we started tracking it.
87 QualType T;
88
89 /// The current state of the object.
90 ///
91 /// See the RefVal::Kind enum for possible values.
92 unsigned RawKind : 5;
93
George Karpenkov27db3302018-12-07 20:21:51 +000094 /// The kind of object being tracked (CF or ObjC or OSObject), if known.
George Karpenkov70c2ee32018-08-17 21:41:07 +000095 ///
George Karpenkov7e3016d2019-01-10 18:13:46 +000096 /// See the ObjKind enum for possible values.
George Karpenkovab0011e2018-08-23 00:26:59 +000097 unsigned RawObjectKind : 3;
George Karpenkov70c2ee32018-08-17 21:41:07 +000098
99 /// True if the current state and/or retain count may turn out to not be the
100 /// best possible approximation of the reference counting state.
101 ///
102 /// If true, the checker may decide to throw away ("override") this state
103 /// in favor of something else when it sees the object being used in new ways.
104 ///
105 /// This setting should not be propagated to state derived from this state.
106 /// Once we start deriving new states, it would be inconsistent to override
107 /// them.
108 unsigned RawIvarAccessHistory : 2;
109
George Karpenkov7e3016d2019-01-10 18:13:46 +0000110 RefVal(Kind k, ObjKind o, unsigned cnt, unsigned acnt, QualType t,
George Karpenkov70c2ee32018-08-17 21:41:07 +0000111 IvarAccessHistory IvarAccess)
112 : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
113 RawObjectKind(static_cast<unsigned>(o)),
114 RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
115 assert(getKind() == k && "not enough bits for the kind");
116 assert(getObjKind() == o && "not enough bits for the object kind");
117 assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
118 }
119
120public:
121 Kind getKind() const { return static_cast<Kind>(RawKind); }
122
George Karpenkov7e3016d2019-01-10 18:13:46 +0000123 ObjKind getObjKind() const {
124 return static_cast<ObjKind>(RawObjectKind);
George Karpenkov70c2ee32018-08-17 21:41:07 +0000125 }
126
127 unsigned getCount() const { return Cnt; }
128 unsigned getAutoreleaseCount() const { return ACnt; }
129 unsigned getCombinedCounts() const { return Cnt + ACnt; }
130 void clearCounts() {
131 Cnt = 0;
132 ACnt = 0;
133 }
134 void setCount(unsigned i) {
135 Cnt = i;
136 }
137 void setAutoreleaseCount(unsigned i) {
138 ACnt = i;
139 }
140
141 QualType getType() const { return T; }
142
143 /// Returns what the analyzer knows about direct accesses to a particular
144 /// instance variable.
145 ///
146 /// If the object with this refcount wasn't originally from an Objective-C
147 /// ivar region, this should always return IvarAccessHistory::None.
148 IvarAccessHistory getIvarAccessHistory() const {
149 return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
150 }
151
152 bool isOwned() const {
153 return getKind() == Owned;
154 }
155
156 bool isNotOwned() const {
157 return getKind() == NotOwned;
158 }
159
160 bool isReturnedOwned() const {
161 return getKind() == ReturnedOwned;
162 }
163
164 bool isReturnedNotOwned() const {
165 return getKind() == ReturnedNotOwned;
166 }
167
168 /// Create a state for an object whose lifetime is the responsibility of the
169 /// current function, at least partially.
170 ///
171 /// Most commonly, this is an owned object with a retain count of +1.
George Karpenkov7e3016d2019-01-10 18:13:46 +0000172 static RefVal makeOwned(ObjKind o, QualType t) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000173 return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None);
174 }
175
176 /// Create a state for an object whose lifetime is not the responsibility of
177 /// the current function.
178 ///
179 /// Most commonly, this is an unowned object with a retain count of +0.
George Karpenkov7e3016d2019-01-10 18:13:46 +0000180 static RefVal makeNotOwned(ObjKind o, QualType t) {
George Karpenkov70c2ee32018-08-17 21:41:07 +0000181 return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None);
182 }
183
184 RefVal operator-(size_t i) const {
185 return RefVal(getKind(), getObjKind(), getCount() - i,
186 getAutoreleaseCount(), getType(), getIvarAccessHistory());
187 }
188
189 RefVal operator+(size_t i) const {
190 return RefVal(getKind(), getObjKind(), getCount() + i,
191 getAutoreleaseCount(), getType(), getIvarAccessHistory());
192 }
193
194 RefVal operator^(Kind k) const {
195 return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
196 getType(), getIvarAccessHistory());
197 }
198
199 RefVal autorelease() const {
200 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
201 getType(), getIvarAccessHistory());
202 }
203
204 RefVal withIvarAccess() const {
205 assert(getIvarAccessHistory() == IvarAccessHistory::None);
206 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
207 getType(), IvarAccessHistory::AccessedDirectly);
208 }
209
210 RefVal releaseViaIvar() const {
211 assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
212 return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
213 getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
214 }
215
216 // Comparison, profiling, and pretty-printing.
George Karpenkov70c2ee32018-08-17 21:41:07 +0000217 bool hasSameState(const RefVal &X) const {
218 return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
219 getIvarAccessHistory() == X.getIvarAccessHistory();
220 }
221
222 bool operator==(const RefVal& X) const {
223 return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
224 }
225
226 void Profile(llvm::FoldingSetNodeID& ID) const {
227 ID.Add(T);
228 ID.AddInteger(RawKind);
229 ID.AddInteger(Cnt);
230 ID.AddInteger(ACnt);
231 ID.AddInteger(RawObjectKind);
232 ID.AddInteger(RawIvarAccessHistory);
233 }
234
235 void print(raw_ostream &Out) const;
236};
237
238class RetainCountChecker
239 : public Checker< check::Bind,
240 check::DeadSymbols,
George Karpenkov70c2ee32018-08-17 21:41:07 +0000241 check::BeginFunction,
242 check::EndFunction,
243 check::PostStmt<BlockExpr>,
244 check::PostStmt<CastExpr>,
245 check::PostStmt<ObjCArrayLiteral>,
246 check::PostStmt<ObjCDictionaryLiteral>,
247 check::PostStmt<ObjCBoxedExpr>,
248 check::PostStmt<ObjCIvarRefExpr>,
249 check::PostCall,
George Karpenkov70c2ee32018-08-17 21:41:07 +0000250 check::RegionChanges,
251 eval::Assume,
252 eval::Call > {
George Karpenkov2c2d0b62019-01-18 19:24:55 +0000253
254 RefCountBug useAfterRelease{this, RefCountBug::UseAfterRelease};
255 RefCountBug releaseNotOwned{this, RefCountBug::ReleaseNotOwned};
256 RefCountBug deallocNotOwned{this, RefCountBug::DeallocNotOwned};
257 RefCountBug freeNotOwned{this, RefCountBug::FreeNotOwned};
258 RefCountBug overAutorelease{this, RefCountBug::OverAutorelease};
259 RefCountBug returnNotOwnedForOwned{this, RefCountBug::ReturnNotOwnedForOwned};
260 RefCountBug leakWithinFunction{this, RefCountBug::LeakWithinFunction};
261 RefCountBug leakAtReturn{this, RefCountBug::LeakAtReturn};
George Karpenkov70c2ee32018-08-17 21:41:07 +0000262
George Karpenkova9e29562019-01-22 19:51:00 +0000263 CheckerProgramPointTag DeallocSentTag{this, "DeallocSent"};
264 CheckerProgramPointTag CastFailTag{this, "DynamicCastFail"};
265
George Karpenkov70c2ee32018-08-17 21:41:07 +0000266 mutable std::unique_ptr<RetainSummaryManager> Summaries;
Kristof Umannc83b0dd2018-11-02 15:48:10 +0000267public:
George Karpenkov27db3302018-12-07 20:21:51 +0000268
269 /// Track Objective-C and CoreFoundation objects.
270 bool TrackObjCAndCFObjects = false;
271
272 /// Track sublcasses of OSObject.
273 bool TrackOSObjects = false;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000274
George Karpenkovd37ff4e2019-01-29 19:29:59 +0000275 /// Track initial parameters (for the entry point) for NS/CF objects.
276 bool TrackNSCFStartParam = false;
277
George Karpenkov2c2d0b62019-01-18 19:24:55 +0000278 RetainCountChecker() {};
George Karpenkov70c2ee32018-08-17 21:41:07 +0000279
280 RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
George Karpenkov6fdd2bd2019-01-25 01:24:04 +0000281 if (!Summaries)
282 Summaries.reset(
283 new RetainSummaryManager(Ctx, TrackObjCAndCFObjects, TrackOSObjects));
George Karpenkov70c2ee32018-08-17 21:41:07 +0000284 return *Summaries;
285 }
286
287 RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
288 return getSummaryManager(C.getASTContext());
289 }
290
291 void printState(raw_ostream &Out, ProgramStateRef State,
292 const char *NL, const char *Sep) const override;
293
294 void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
295 void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
296 void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
297
298 void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
299 void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
300 void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
301
302 void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
303
304 void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
305
306 void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
307 CheckerContext &C) const;
308
309 void processSummaryOfInlined(const RetainSummary &Summ,
310 const CallEvent &Call,
311 CheckerContext &C) const;
312
313 bool evalCall(const CallExpr *CE, CheckerContext &C) const;
314
315 ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
316 bool Assumption) const;
317
318 ProgramStateRef
319 checkRegionChanges(ProgramStateRef state,
320 const InvalidatedSymbols *invalidated,
321 ArrayRef<const MemRegion *> ExplicitRegions,
322 ArrayRef<const MemRegion *> Regions,
323 const LocationContext* LCtx,
324 const CallEvent *Call) const;
325
George Karpenkov04553e52018-09-21 20:37:20 +0000326 ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
George Karpenkov70c2ee32018-08-17 21:41:07 +0000327 ExplodedNode *Pred, RetEffect RE, RefVal X,
328 SymbolRef Sym, ProgramStateRef state) const;
329
330 void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
331 void checkBeginFunction(CheckerContext &C) const;
332 void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
333
334 ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
George Karpenkov9cbcc212019-01-10 18:14:12 +0000335 RefVal V, ArgEffect E, RefVal::Kind &hasErr,
George Karpenkov70c2ee32018-08-17 21:41:07 +0000336 CheckerContext &C) const;
337
George Karpenkov2c2d0b62019-01-18 19:24:55 +0000338 const RefCountBug &errorKindToBugKind(RefVal::Kind ErrorKind,
339 SymbolRef Sym) const;
340
George Karpenkov70c2ee32018-08-17 21:41:07 +0000341 void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
342 RefVal::Kind ErrorKind, SymbolRef Sym,
343 CheckerContext &C) const;
344
345 void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
346
George Karpenkov70c2ee32018-08-17 21:41:07 +0000347 ProgramStateRef handleSymbolDeath(ProgramStateRef state,
348 SymbolRef sid, RefVal V,
349 SmallVectorImpl<SymbolRef> &Leaked) const;
350
351 ProgramStateRef
352 handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
353 const ProgramPointTag *Tag, CheckerContext &Ctx,
George Karpenkov04553e52018-09-21 20:37:20 +0000354 SymbolRef Sym,
355 RefVal V,
356 const ReturnStmt *S=nullptr) const;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000357
358 ExplodedNode *processLeaks(ProgramStateRef state,
359 SmallVectorImpl<SymbolRef> &Leaked,
360 CheckerContext &Ctx,
361 ExplodedNode *Pred = nullptr) const;
George Karpenkov04553e52018-09-21 20:37:20 +0000362
George Karpenkova9e29562019-01-22 19:51:00 +0000363 const CheckerProgramPointTag &getDeallocSentTag() const {
364 return DeallocSentTag;
365 }
366
367 const CheckerProgramPointTag &getCastFailTag() const {
368 return CastFailTag;
369 }
370
George Karpenkov04553e52018-09-21 20:37:20 +0000371private:
372 /// Perform the necessary checks and state adjustments at the end of the
373 /// function.
374 /// \p S Return statement, may be null.
375 ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const;
George Karpenkov70c2ee32018-08-17 21:41:07 +0000376};
377
378//===----------------------------------------------------------------------===//
379// RefBindings - State used to track object reference counts.
380//===----------------------------------------------------------------------===//
381
382const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
383
George Karpenkov70c2ee32018-08-17 21:41:07 +0000384/// Returns true if this stack frame is for an Objective-C method that is a
385/// property getter or setter whose body has been synthesized by the analyzer.
386inline bool isSynthesizedAccessor(const StackFrameContext *SFC) {
387 auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
388 if (!Method || !Method->isPropertyAccessor())
389 return false;
390
391 return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
392}
393
394} // end namespace retaincountchecker
395} // end namespace ento
396} // end namespace clang
397
398#endif