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/STLExtras.h"
40#include "llvm/ADT/SmallString.h"
41#include "llvm/ADT/StringExtras.h"
42#include <cstdarg>
43#include <utility>
44
45namespace clang {
46namespace ento {
47namespace retaincountchecker {
48
49/// Metadata on reference.
50class RefVal {
51public:
52  enum Kind {
53    Owned = 0, // Owning reference.
54    NotOwned,  // Reference is not owned by still valid (not freed).
55    Released,  // Object has been released.
56    ReturnedOwned, // Returned object passes ownership to caller.
57    ReturnedNotOwned, // Return object does not pass ownership to caller.
58    ERROR_START,
59    ErrorDeallocNotOwned, // -dealloc called on non-owned object.
60    ErrorUseAfterRelease, // Object used after released.
61    ErrorReleaseNotOwned, // Release of an object that was not owned.
62    ERROR_LEAK_START,
63    ErrorLeak,  // A memory leak due to excessive reference counts.
64    ErrorLeakReturned, // A memory leak due to the returning method not having
65                       // the correct naming conventions.
66    ErrorOverAutorelease,
67    ErrorReturnedNotOwned
68  };
69
70  /// Tracks how an object referenced by an ivar has been used.
71  ///
72  /// This accounts for us not knowing if an arbitrary ivar is supposed to be
73  /// stored at +0 or +1.
74  enum class IvarAccessHistory {
75    None,
76    AccessedDirectly,
77    ReleasedAfterDirectAccess
78  };
79
80private:
81  /// The number of outstanding retains.
82  unsigned Cnt;
83  /// The number of outstanding autoreleases.
84  unsigned ACnt;
85  /// The (static) type of the object at the time we started tracking it.
86  QualType T;
87
88  /// The current state of the object.
89  ///
90  /// See the RefVal::Kind enum for possible values.
91  unsigned RawKind : 5;
92
93  /// The kind of object being tracked (CF or ObjC or OSObject), if known.
94  ///
95  /// See the ObjKind enum for possible values.
96  unsigned RawObjectKind : 3;
97
98  /// True if the current state and/or retain count may turn out to not be the
99  /// best possible approximation of the reference counting state.
100  ///
101  /// If true, the checker may decide to throw away ("override") this state
102  /// in favor of something else when it sees the object being used in new ways.
103  ///
104  /// This setting should not be propagated to state derived from this state.
105  /// Once we start deriving new states, it would be inconsistent to override
106  /// them.
107  unsigned RawIvarAccessHistory : 2;
108
109  RefVal(Kind k, ObjKind o, unsigned cnt, unsigned acnt, QualType t,
110         IvarAccessHistory IvarAccess)
111    : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
112      RawObjectKind(static_cast<unsigned>(o)),
113      RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
114    assert(getKind() == k && "not enough bits for the kind");
115    assert(getObjKind() == o && "not enough bits for the object kind");
116    assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
117  }
118
119public:
120  Kind getKind() const { return static_cast<Kind>(RawKind); }
121
122  ObjKind getObjKind() const {
123    return static_cast<ObjKind>(RawObjectKind);
124  }
125
126  unsigned getCount() const { return Cnt; }
127  unsigned getAutoreleaseCount() const { return ACnt; }
128  unsigned getCombinedCounts() const { return Cnt + ACnt; }
129  void clearCounts() {
130    Cnt = 0;
131    ACnt = 0;
132  }
133  void setCount(unsigned i) {
134    Cnt = i;
135  }
136  void setAutoreleaseCount(unsigned i) {
137    ACnt = i;
138  }
139
140  QualType getType() const { return T; }
141
142  /// Returns what the analyzer knows about direct accesses to a particular
143  /// instance variable.
144  ///
145  /// If the object with this refcount wasn't originally from an Objective-C
146  /// ivar region, this should always return IvarAccessHistory::None.
147  IvarAccessHistory getIvarAccessHistory() const {
148    return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
149  }
150
151  bool isOwned() const {
152    return getKind() == Owned;
153  }
154
155  bool isNotOwned() const {
156    return getKind() == NotOwned;
157  }
158
159  bool isReturnedOwned() const {
160    return getKind() == ReturnedOwned;
161  }
162
163  bool isReturnedNotOwned() const {
164    return getKind() == ReturnedNotOwned;
165  }
166
167  /// Create a state for an object whose lifetime is the responsibility of the
168  /// current function, at least partially.
169  ///
170  /// Most commonly, this is an owned object with a retain count of +1.
171  static RefVal makeOwned(ObjKind o, QualType t) {
172    return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None);
173  }
174
175  /// Create a state for an object whose lifetime is not the responsibility of
176  /// the current function.
177  ///
178  /// Most commonly, this is an unowned object with a retain count of +0.
179  static RefVal makeNotOwned(ObjKind o, QualType t) {
180    return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None);
181  }
182
183  RefVal operator-(size_t i) const {
184    return RefVal(getKind(), getObjKind(), getCount() - i,
185                  getAutoreleaseCount(), getType(), getIvarAccessHistory());
186  }
187
188  RefVal operator+(size_t i) const {
189    return RefVal(getKind(), getObjKind(), getCount() + i,
190                  getAutoreleaseCount(), getType(), getIvarAccessHistory());
191  }
192
193  RefVal operator^(Kind k) const {
194    return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
195                  getType(), getIvarAccessHistory());
196  }
197
198  RefVal autorelease() const {
199    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
200                  getType(), getIvarAccessHistory());
201  }
202
203  RefVal withIvarAccess() const {
204    assert(getIvarAccessHistory() == IvarAccessHistory::None);
205    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
206                  getType(), IvarAccessHistory::AccessedDirectly);
207  }
208
209  RefVal releaseViaIvar() const {
210    assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
211    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
212                  getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
213  }
214
215  // Comparison, profiling, and pretty-printing.
216  bool hasSameState(const RefVal &X) const {
217    return getKind() == X.getKind() && Cnt == X.Cnt && ACnt == X.ACnt &&
218           getIvarAccessHistory() == X.getIvarAccessHistory();
219  }
220
221  bool operator==(const RefVal& X) const {
222    return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
223  }
224
225  void Profile(llvm::FoldingSetNodeID& ID) const {
226    ID.Add(T);
227    ID.AddInteger(RawKind);
228    ID.AddInteger(Cnt);
229    ID.AddInteger(ACnt);
230    ID.AddInteger(RawObjectKind);
231    ID.AddInteger(RawIvarAccessHistory);
232  }
233
234  void print(raw_ostream &Out) const;
235};
236
237class RetainCountChecker
238  : public Checker< check::Bind,
239                    check::DeadSymbols,
240                    check::BeginFunction,
241                    check::EndFunction,
242                    check::PostStmt<BlockExpr>,
243                    check::PostStmt<CastExpr>,
244                    check::PostStmt<ObjCArrayLiteral>,
245                    check::PostStmt<ObjCDictionaryLiteral>,
246                    check::PostStmt<ObjCBoxedExpr>,
247                    check::PostStmt<ObjCIvarRefExpr>,
248                    check::PostCall,
249                    check::RegionChanges,
250                    eval::Assume,
251                    eval::Call > {
252
253public:
254  std::unique_ptr<RefCountBug> UseAfterRelease;
255  std::unique_ptr<RefCountBug> ReleaseNotOwned;
256  std::unique_ptr<RefCountBug> DeallocNotOwned;
257  std::unique_ptr<RefCountBug> FreeNotOwned;
258  std::unique_ptr<RefCountBug> OverAutorelease;
259  std::unique_ptr<RefCountBug> ReturnNotOwnedForOwned;
260  std::unique_ptr<RefCountBug> LeakWithinFunction;
261  std::unique_ptr<RefCountBug> LeakAtReturn;
262
263  mutable std::unique_ptr<RetainSummaryManager> Summaries;
264
265  static std::unique_ptr<CheckerProgramPointTag> DeallocSentTag;
266  static std::unique_ptr<CheckerProgramPointTag> CastFailTag;
267
268  /// Track Objective-C and CoreFoundation objects.
269  bool TrackObjCAndCFObjects = false;
270
271  /// Track sublcasses of OSObject.
272  bool TrackOSObjects = false;
273
274  /// Track initial parameters (for the entry point) for NS/CF objects.
275  bool TrackNSCFStartParam = false;
276
277  RetainCountChecker() {};
278
279  RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
280    if (!Summaries)
281      Summaries.reset(
282          new RetainSummaryManager(Ctx, TrackObjCAndCFObjects, TrackOSObjects));
283    return *Summaries;
284  }
285
286  RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
287    return getSummaryManager(C.getASTContext());
288  }
289
290  void printState(raw_ostream &Out, ProgramStateRef State,
291                  const char *NL, const char *Sep) const override;
292
293  void checkBind(SVal loc, SVal val, const Stmt *S, CheckerContext &C) const;
294  void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const;
295  void checkPostStmt(const CastExpr *CE, CheckerContext &C) const;
296
297  void checkPostStmt(const ObjCArrayLiteral *AL, CheckerContext &C) const;
298  void checkPostStmt(const ObjCDictionaryLiteral *DL, CheckerContext &C) const;
299  void checkPostStmt(const ObjCBoxedExpr *BE, CheckerContext &C) const;
300
301  void checkPostStmt(const ObjCIvarRefExpr *IRE, CheckerContext &C) const;
302
303  void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
304
305  void checkSummary(const RetainSummary &Summ, const CallEvent &Call,
306                    CheckerContext &C) const;
307
308  void processSummaryOfInlined(const RetainSummary &Summ,
309                               const CallEvent &Call,
310                               CheckerContext &C) const;
311
312  bool evalCall(const CallEvent &Call, CheckerContext &C) const;
313
314  ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond,
315                                 bool Assumption) const;
316
317  ProgramStateRef
318  checkRegionChanges(ProgramStateRef state,
319                     const InvalidatedSymbols *invalidated,
320                     ArrayRef<const MemRegion *> ExplicitRegions,
321                     ArrayRef<const MemRegion *> Regions,
322                     const LocationContext* LCtx,
323                     const CallEvent *Call) const;
324
325  ExplodedNode* checkReturnWithRetEffect(const ReturnStmt *S, CheckerContext &C,
326                                ExplodedNode *Pred, RetEffect RE, RefVal X,
327                                SymbolRef Sym, ProgramStateRef state) const;
328
329  void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const;
330  void checkBeginFunction(CheckerContext &C) const;
331  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
332
333  ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
334                               RefVal V, ArgEffect E, RefVal::Kind &hasErr,
335                               CheckerContext &C) const;
336
337  const RefCountBug &errorKindToBugKind(RefVal::Kind ErrorKind,
338                                        SymbolRef Sym) const;
339
340  void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
341                           RefVal::Kind ErrorKind, SymbolRef Sym,
342                           CheckerContext &C) const;
343
344  void processObjCLiterals(CheckerContext &C, const Expr *Ex) const;
345
346  ProgramStateRef handleSymbolDeath(ProgramStateRef state,
347                                    SymbolRef sid, RefVal V,
348                                    SmallVectorImpl<SymbolRef> &Leaked) const;
349
350  ProgramStateRef
351  handleAutoreleaseCounts(ProgramStateRef state, ExplodedNode *Pred,
352                          const ProgramPointTag *Tag, CheckerContext &Ctx,
353                          SymbolRef Sym,
354                          RefVal V,
355                          const ReturnStmt *S=nullptr) const;
356
357  ExplodedNode *processLeaks(ProgramStateRef state,
358                             SmallVectorImpl<SymbolRef> &Leaked,
359                             CheckerContext &Ctx,
360                             ExplodedNode *Pred = nullptr) const;
361
362  static const CheckerProgramPointTag &getDeallocSentTag() {
363    return *DeallocSentTag;
364  }
365
366  static const CheckerProgramPointTag &getCastFailTag() { return *CastFailTag; }
367
368private:
369  /// Perform the necessary checks and state adjustments at the end of the
370  /// function.
371  /// \p S Return statement, may be null.
372  ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const;
373};
374
375//===----------------------------------------------------------------------===//
376// RefBindings - State used to track object reference counts.
377//===----------------------------------------------------------------------===//
378
379const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
380
381/// Returns true if this stack frame is for an Objective-C method that is a
382/// property getter or setter whose body has been synthesized by the analyzer.
383inline bool isSynthesizedAccessor(const StackFrameContext *SFC) {
384  auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
385  if (!Method || !Method->isPropertyAccessor())
386    return false;
387
388  return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
389}
390
391} // end namespace retaincountchecker
392} // end namespace ento
393} // end namespace clang
394
395#endif
396