• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /freebsd-12-stable/contrib/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/
1//==--- RetainCountChecker.h - Checks for leaks and other issues -*- C++ -*--//
2//
3// 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
6//
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
17#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
18#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"
24#include "clang/Analysis/PathDiagnostic.h"
25#include "clang/Analysis/RetainSummaryManager.h"
26#include "clang/Basic/LangOptions.h"
27#include "clang/Basic/SourceManager.h"
28#include "clang/Analysis/SelectorExtras.h"
29#include "clang/StaticAnalyzer/Core/BugReporter/BugType.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
46namespace 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
94  /// The kind of object being tracked (CF or ObjC or OSObject), if known.
95  ///
96  /// See the ObjKind enum for possible values.
97  unsigned RawObjectKind : 3;
98
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
110  RefVal(Kind k, ObjKind o, unsigned cnt, unsigned acnt, QualType t,
111         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
123  ObjKind getObjKind() const {
124    return static_cast<ObjKind>(RawObjectKind);
125  }
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.
172  static RefVal makeOwned(ObjKind o, QualType t) {
173    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.
180  static RefVal makeNotOwned(ObjKind o, QualType t) {
181    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.
217  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,
241                    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,
250                    check::RegionChanges,
251                    eval::Assume,
252                    eval::Call > {
253
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};
262
263  CheckerProgramPointTag DeallocSentTag{this, "DeallocSent"};
264  CheckerProgramPointTag CastFailTag{this, "DynamicCastFail"};
265
266  mutable std::unique_ptr<RetainSummaryManager> Summaries;
267public:
268
269  /// Track Objective-C and CoreFoundation objects.
270  bool TrackObjCAndCFObjects = false;
271
272  /// Track sublcasses of OSObject.
273  bool TrackOSObjects = false;
274
275  /// Track initial parameters (for the entry point) for NS/CF objects.
276  bool TrackNSCFStartParam = false;
277
278  RetainCountChecker() {};
279
280  RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
281    if (!Summaries)
282      Summaries.reset(
283          new RetainSummaryManager(Ctx, TrackObjCAndCFObjects, TrackOSObjects));
284    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 CallEvent &Call, 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
326  ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
327                                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,
335                               RefVal V, ArgEffect E, RefVal::Kind &hasErr,
336                               CheckerContext &C) const;
337
338  const RefCountBug &errorKindToBugKind(RefVal::Kind ErrorKind,
339                                        SymbolRef Sym) const;
340
341  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
347  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,
354                          SymbolRef Sym,
355                          RefVal V,
356                          const ReturnStmt *S=nullptr) const;
357
358  ExplodedNode *processLeaks(ProgramStateRef state,
359                             SmallVectorImpl<SymbolRef> &Leaked,
360                             CheckerContext &Ctx,
361                             ExplodedNode *Pred = nullptr) const;
362
363  const CheckerProgramPointTag &getDeallocSentTag() const {
364    return DeallocSentTag;
365  }
366
367  const CheckerProgramPointTag &getCastFailTag() const {
368    return CastFailTag;
369  }
370
371private:
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;
376};
377
378//===----------------------------------------------------------------------===//
379// RefBindings - State used to track object reference counts.
380//===----------------------------------------------------------------------===//
381
382const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
383
384/// 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
399