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 
45 namespace clang {
46 namespace ento {
47 namespace retaincountchecker {
48 
49 /// Metadata on reference.
50 class RefVal {
51 public:
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 
80 private:
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 
119 public:
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 
237 class 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 
253 public:
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 
368 private:
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 
379 const 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.
383 inline 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