Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
Line
Count
Source
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
46
namespace clang {
47
namespace ento {
48
namespace retaincountchecker {
49
50
/// Metadata on reference.
51
class RefVal {
52
public:
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
81
private:
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
5.06k
    : Cnt(cnt), ACnt(acnt), T(t), RawKind(static_cast<unsigned>(k)),
113
5.06k
      RawObjectKind(static_cast<unsigned>(o)),
114
5.06k
      RawIvarAccessHistory(static_cast<unsigned>(IvarAccess)) {
115
5.06k
    assert(getKind() == k && "not enough bits for the kind");
116
5.06k
    assert(getObjKind() == o && "not enough bits for the object kind");
117
5.06k
    assert(getIvarAccessHistory() == IvarAccess && "not enough bits");
118
5.06k
  }
119
120
public:
121
47.5k
  Kind getKind() const { return static_cast<Kind>(RawKind); }
122
123
20.4k
  ObjKind getObjKind() const {
124
20.4k
    return static_cast<ObjKind>(RawObjectKind);
125
20.4k
  }
126
127
7.13k
  unsigned getCount() const { return Cnt; }
128
5.82k
  unsigned getAutoreleaseCount() const { return ACnt; }
129
5
  unsigned getCombinedCounts() const { return Cnt + ACnt; }
130
118
  void clearCounts() {
131
118
    Cnt = 0;
132
118
    ACnt = 0;
133
118
  }
134
219
  void setCount(unsigned i) {
135
219
    Cnt = i;
136
219
  }
137
20
  void setAutoreleaseCount(unsigned i) {
138
20
    ACnt = i;
139
20
  }
140
141
4.34k
  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
42.7k
  IvarAccessHistory getIvarAccessHistory() const {
149
42.7k
    return static_cast<IvarAccessHistory>(RawIvarAccessHistory);
150
42.7k
  }
151
152
2.07k
  bool isOwned() const {
153
2.07k
    return getKind() == Owned;
154
2.07k
  }
155
156
1.36k
  bool isNotOwned() const {
157
1.36k
    return getKind() == NotOwned;
158
1.36k
  }
159
160
1.05k
  bool isReturnedOwned() const {
161
1.05k
    return getKind() == ReturnedOwned;
162
1.05k
  }
163
164
82
  bool isReturnedNotOwned() const {
165
82
    return getKind() == ReturnedNotOwned;
166
82
  }
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
1.38k
  static RefVal makeOwned(ObjKind o, QualType t) {
173
1.38k
    return RefVal(Owned, o, /*Count=*/1, 0, t, IvarAccessHistory::None);
174
1.38k
  }
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
553
  static RefVal makeNotOwned(ObjKind o, QualType t) {
181
553
    return RefVal(NotOwned, o, /*Count=*/0, 0, t, IvarAccessHistory::None);
182
553
  }
183
184
818
  RefVal operator-(size_t i) const {
185
818
    return RefVal(getKind(), getObjKind(), getCount() - i,
186
818
                  getAutoreleaseCount(), getType(), getIvarAccessHistory());
187
818
  }
188
189
226
  RefVal operator+(size_t i) const {
190
226
    return RefVal(getKind(), getObjKind(), getCount() + i,
191
226
                  getAutoreleaseCount(), getType(), getIvarAccessHistory());
192
226
  }
193
194
1.77k
  RefVal operator^(Kind k) const {
195
1.77k
    return RefVal(k, getObjKind(), getCount(), getAutoreleaseCount(),
196
1.77k
                  getType(), getIvarAccessHistory());
197
1.77k
  }
198
199
159
  RefVal autorelease() const {
200
159
    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount()+1,
201
159
                  getType(), getIvarAccessHistory());
202
159
  }
203
204
109
  RefVal withIvarAccess() const {
205
109
    assert(getIvarAccessHistory() == IvarAccessHistory::None);
206
109
    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
207
109
                  getType(), IvarAccessHistory::AccessedDirectly);
208
109
  }
209
210
48
  RefVal releaseViaIvar() const {
211
48
    assert(getIvarAccessHistory() == IvarAccessHistory::AccessedDirectly);
212
48
    return RefVal(getKind(), getObjKind(), getCount(), getAutoreleaseCount(),
213
48
                  getType(), IvarAccessHistory::ReleasedAfterDirectAccess);
214
48
  }
215
216
  // Comparison, profiling, and pretty-printing.
217
16.0k
  bool hasSameState(const RefVal &X) const {
218
16.0k
    return getKind() == X.getKind() && 
Cnt == X.Cnt15.9k
&&
ACnt == X.ACnt15.8k
&&
219
16.0k
           
getIvarAccessHistory() == X.getIvarAccessHistory()15.7k
;
220
16.0k
  }
221
222
5.17k
  bool operator==(const RefVal& X) const {
223
5.17k
    return T == X.T && hasSameState(X) && getObjKind() == X.getObjKind();
224
5.17k
  }
225
226
10.3k
  void Profile(llvm::FoldingSetNodeID& ID) const {
227
10.3k
    ID.Add(T);
228
10.3k
    ID.AddInteger(RawKind);
229
10.3k
    ID.AddInteger(Cnt);
230
10.3k
    ID.AddInteger(ACnt);
231
10.3k
    ID.AddInteger(RawObjectKind);
232
10.3k
    ID.AddInteger(RawIvarAccessHistory);
233
10.3k
  }
234
235
  void print(raw_ostream &Out) const;
236
};
237
238
class 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
public:
255
  std::unique_ptr<RefCountBug> UseAfterRelease;
256
  std::unique_ptr<RefCountBug> ReleaseNotOwned;
257
  std::unique_ptr<RefCountBug> DeallocNotOwned;
258
  std::unique_ptr<RefCountBug> FreeNotOwned;
259
  std::unique_ptr<RefCountBug> OverAutorelease;
260
  std::unique_ptr<RefCountBug> ReturnNotOwnedForOwned;
261
  std::unique_ptr<RefCountBug> LeakWithinFunction;
262
  std::unique_ptr<RefCountBug> LeakAtReturn;
263
264
  mutable std::unique_ptr<RetainSummaryManager> Summaries;
265
266
  static std::unique_ptr<CheckerProgramPointTag> DeallocSentTag;
267
  static std::unique_ptr<CheckerProgramPointTag> CastFailTag;
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
96
  RetainCountChecker() {};
279
280
8.56k
  RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
281
8.56k
    if (!Summaries)
282
96
      Summaries.reset(
283
96
          new RetainSummaryManager(Ctx, TrackObjCAndCFObjects, TrackOSObjects));
284
8.56k
    return *Summaries;
285
8.56k
  }
286
287
8.56k
  RetainSummaryManager &getSummaryManager(CheckerContext &C) const {
288
8.56k
    return getSummaryManager(C.getASTContext());
289
8.56k
  }
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
10.8k
  static const CheckerProgramPointTag &getDeallocSentTag() {
364
10.8k
    return *DeallocSentTag;
365
10.8k
  }
366
367
10.8k
  static const CheckerProgramPointTag &getCastFailTag() { return *CastFailTag; }
368
369
private:
370
  /// Perform the necessary checks and state adjustments at the end of the
371
  /// function.
372
  /// \p S Return statement, may be null.
373
  ExplodedNode * processReturn(const ReturnStmt *S, CheckerContext &C) const;
374
};
375
376
//===----------------------------------------------------------------------===//
377
// RefBindings - State used to track object reference counts.
378
//===----------------------------------------------------------------------===//
379
380
const RefVal *getRefBinding(ProgramStateRef State, SymbolRef Sym);
381
382
/// Returns true if this stack frame is for an Objective-C method that is a
383
/// property getter or setter whose body has been synthesized by the analyzer.
384
165
inline bool isSynthesizedAccessor(const StackFrameContext *SFC) {
385
165
  auto Method = dyn_cast_or_null<ObjCMethodDecl>(SFC->getDecl());
386
165
  if (!Method || !Method->isPropertyAccessor())
387
109
    return false;
388
389
56
  return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
390
165
}
391
392
} // end namespace retaincountchecker
393
} // end namespace ento
394
} // end namespace clang
395
396
#endif