RetainCountDiagnostics.cpp revision 360784
1// RetainCountDiagnostics.cpp - 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 diagnostics for RetainCountChecker, which implements
10//  a reference count checker for Core Foundation and Cocoa on (Mac OS X).
11//
12//===----------------------------------------------------------------------===//
13
14#include "RetainCountDiagnostics.h"
15#include "RetainCountChecker.h"
16
17using namespace clang;
18using namespace ento;
19using namespace retaincountchecker;
20
21StringRef RefCountBug::bugTypeToName(RefCountBug::RefCountBugType BT) {
22  switch (BT) {
23  case UseAfterRelease:
24    return "Use-after-release";
25  case ReleaseNotOwned:
26    return "Bad release";
27  case DeallocNotOwned:
28    return "-dealloc sent to non-exclusively owned object";
29  case FreeNotOwned:
30    return "freeing non-exclusively owned object";
31  case OverAutorelease:
32    return "Object autoreleased too many times";
33  case ReturnNotOwnedForOwned:
34    return "Method should return an owned object";
35  case LeakWithinFunction:
36    return "Leak";
37  case LeakAtReturn:
38    return "Leak of returned object";
39  }
40  llvm_unreachable("Unknown RefCountBugType");
41}
42
43StringRef RefCountBug::getDescription() const {
44  switch (BT) {
45  case UseAfterRelease:
46    return "Reference-counted object is used after it is released";
47  case ReleaseNotOwned:
48    return "Incorrect decrement of the reference count of an object that is "
49           "not owned at this point by the caller";
50  case DeallocNotOwned:
51    return "-dealloc sent to object that may be referenced elsewhere";
52  case FreeNotOwned:
53    return  "'free' called on an object that may be referenced elsewhere";
54  case OverAutorelease:
55    return "Object autoreleased too many times";
56  case ReturnNotOwnedForOwned:
57    return "Object with a +0 retain count returned to caller where a +1 "
58           "(owning) retain count is expected";
59  case LeakWithinFunction:
60  case LeakAtReturn:
61    return "";
62  }
63  llvm_unreachable("Unknown RefCountBugType");
64}
65
66RefCountBug::RefCountBug(const CheckerBase *Checker, RefCountBugType BT)
67    : BugType(Checker, bugTypeToName(BT), categories::MemoryRefCount,
68              /*SuppressOnSink=*/BT == LeakWithinFunction || BT == LeakAtReturn),
69      BT(BT), Checker(Checker) {}
70
71static bool isNumericLiteralExpression(const Expr *E) {
72  // FIXME: This set of cases was copied from SemaExprObjC.
73  return isa<IntegerLiteral>(E) ||
74         isa<CharacterLiteral>(E) ||
75         isa<FloatingLiteral>(E) ||
76         isa<ObjCBoolLiteralExpr>(E) ||
77         isa<CXXBoolLiteralExpr>(E);
78}
79
80/// If type represents a pointer to CXXRecordDecl,
81/// and is not a typedef, return the decl name.
82/// Otherwise, return the serialization of type.
83static std::string getPrettyTypeName(QualType QT) {
84  QualType PT = QT->getPointeeType();
85  if (!PT.isNull() && !QT->getAs<TypedefType>())
86    if (const auto *RD = PT->getAsCXXRecordDecl())
87      return RD->getName();
88  return QT.getAsString();
89}
90
91/// Write information about the type state change to {@code os},
92/// return whether the note should be generated.
93static bool shouldGenerateNote(llvm::raw_string_ostream &os,
94                               const RefVal *PrevT,
95                               const RefVal &CurrV,
96                               bool DeallocSent) {
97  // Get the previous type state.
98  RefVal PrevV = *PrevT;
99
100  // Specially handle -dealloc.
101  if (DeallocSent) {
102    // Determine if the object's reference count was pushed to zero.
103    assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
104    // We may not have transitioned to 'release' if we hit an error.
105    // This case is handled elsewhere.
106    if (CurrV.getKind() == RefVal::Released) {
107      assert(CurrV.getCombinedCounts() == 0);
108      os << "Object released by directly sending the '-dealloc' message";
109      return true;
110    }
111  }
112
113  // Determine if the typestate has changed.
114  if (!PrevV.hasSameState(CurrV))
115    switch (CurrV.getKind()) {
116    case RefVal::Owned:
117    case RefVal::NotOwned:
118      if (PrevV.getCount() == CurrV.getCount()) {
119        // Did an autorelease message get sent?
120        if (PrevV.getAutoreleaseCount() == CurrV.getAutoreleaseCount())
121          return false;
122
123        assert(PrevV.getAutoreleaseCount() < CurrV.getAutoreleaseCount());
124        os << "Object autoreleased";
125        return true;
126      }
127
128      if (PrevV.getCount() > CurrV.getCount())
129        os << "Reference count decremented.";
130      else
131        os << "Reference count incremented.";
132
133      if (unsigned Count = CurrV.getCount())
134        os << " The object now has a +" << Count << " retain count.";
135
136      return true;
137
138    case RefVal::Released:
139      if (CurrV.getIvarAccessHistory() ==
140              RefVal::IvarAccessHistory::ReleasedAfterDirectAccess &&
141          CurrV.getIvarAccessHistory() != PrevV.getIvarAccessHistory()) {
142        os << "Strong instance variable relinquished. ";
143      }
144      os << "Object released.";
145      return true;
146
147    case RefVal::ReturnedOwned:
148      // Autoreleases can be applied after marking a node ReturnedOwned.
149      if (CurrV.getAutoreleaseCount())
150        return false;
151
152      os << "Object returned to caller as an owning reference (single "
153            "retain count transferred to caller)";
154      return true;
155
156    case RefVal::ReturnedNotOwned:
157      os << "Object returned to caller with a +0 retain count";
158      return true;
159
160    default:
161      return false;
162    }
163  return true;
164}
165
166/// Finds argument index of the out paramter in the call {@code S}
167/// corresponding to the symbol {@code Sym}.
168/// If none found, returns None.
169static Optional<unsigned> findArgIdxOfSymbol(ProgramStateRef CurrSt,
170                                             const LocationContext *LCtx,
171                                             SymbolRef &Sym,
172                                             Optional<CallEventRef<>> CE) {
173  if (!CE)
174    return None;
175
176  for (unsigned Idx = 0; Idx < (*CE)->getNumArgs(); Idx++)
177    if (const MemRegion *MR = (*CE)->getArgSVal(Idx).getAsRegion())
178      if (const auto *TR = dyn_cast<TypedValueRegion>(MR))
179        if (CurrSt->getSVal(MR, TR->getValueType()).getAsSymExpr() == Sym)
180          return Idx;
181
182  return None;
183}
184
185static Optional<std::string> findMetaClassAlloc(const Expr *Callee) {
186  if (const auto *ME = dyn_cast<MemberExpr>(Callee)) {
187    if (ME->getMemberDecl()->getNameAsString() != "alloc")
188      return None;
189    const Expr *This = ME->getBase()->IgnoreParenImpCasts();
190    if (const auto *DRE = dyn_cast<DeclRefExpr>(This)) {
191      const ValueDecl *VD = DRE->getDecl();
192      if (VD->getNameAsString() != "metaClass")
193        return None;
194
195      if (const auto *RD = dyn_cast<CXXRecordDecl>(VD->getDeclContext()))
196        return RD->getNameAsString();
197
198    }
199  }
200  return None;
201}
202
203static std::string findAllocatedObjectName(const Stmt *S, QualType QT) {
204  if (const auto *CE = dyn_cast<CallExpr>(S))
205    if (auto Out = findMetaClassAlloc(CE->getCallee()))
206      return *Out;
207  return getPrettyTypeName(QT);
208}
209
210static void generateDiagnosticsForCallLike(ProgramStateRef CurrSt,
211                                           const LocationContext *LCtx,
212                                           const RefVal &CurrV, SymbolRef &Sym,
213                                           const Stmt *S,
214                                           llvm::raw_string_ostream &os) {
215  CallEventManager &Mgr = CurrSt->getStateManager().getCallEventManager();
216  if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
217    // Get the name of the callee (if it is available)
218    // from the tracked SVal.
219    SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx);
220    const FunctionDecl *FD = X.getAsFunctionDecl();
221
222    // If failed, try to get it from AST.
223    if (!FD)
224      FD = dyn_cast<FunctionDecl>(CE->getCalleeDecl());
225
226    if (const auto *MD = dyn_cast<CXXMethodDecl>(CE->getCalleeDecl())) {
227      os << "Call to method '" << MD->getQualifiedNameAsString() << '\'';
228    } else if (FD) {
229      os << "Call to function '" << FD->getQualifiedNameAsString() << '\'';
230    } else {
231      os << "function call";
232    }
233  } else if (isa<CXXNewExpr>(S)) {
234    os << "Operator 'new'";
235  } else {
236    assert(isa<ObjCMessageExpr>(S));
237    CallEventRef<ObjCMethodCall> Call =
238        Mgr.getObjCMethodCall(cast<ObjCMessageExpr>(S), CurrSt, LCtx);
239
240    switch (Call->getMessageKind()) {
241    case OCM_Message:
242      os << "Method";
243      break;
244    case OCM_PropertyAccess:
245      os << "Property";
246      break;
247    case OCM_Subscript:
248      os << "Subscript";
249      break;
250    }
251  }
252
253  Optional<CallEventRef<>> CE = Mgr.getCall(S, CurrSt, LCtx);
254  auto Idx = findArgIdxOfSymbol(CurrSt, LCtx, Sym, CE);
255
256  // If index is not found, we assume that the symbol was returned.
257  if (!Idx) {
258    os << " returns ";
259  } else {
260    os << " writes ";
261  }
262
263  if (CurrV.getObjKind() == ObjKind::CF) {
264    os << "a Core Foundation object of type '"
265       << Sym->getType().getAsString() << "' with a ";
266  } else if (CurrV.getObjKind() == ObjKind::OS) {
267    os << "an OSObject of type '" << findAllocatedObjectName(S, Sym->getType())
268       << "' with a ";
269  } else if (CurrV.getObjKind() == ObjKind::Generalized) {
270    os << "an object of type '" << Sym->getType().getAsString()
271       << "' with a ";
272  } else {
273    assert(CurrV.getObjKind() == ObjKind::ObjC);
274    QualType T = Sym->getType();
275    if (!isa<ObjCObjectPointerType>(T)) {
276      os << "an Objective-C object with a ";
277    } else {
278      const ObjCObjectPointerType *PT = cast<ObjCObjectPointerType>(T);
279      os << "an instance of " << PT->getPointeeType().getAsString()
280         << " with a ";
281    }
282  }
283
284  if (CurrV.isOwned()) {
285    os << "+1 retain count";
286  } else {
287    assert(CurrV.isNotOwned());
288    os << "+0 retain count";
289  }
290
291  if (Idx) {
292    os << " into an out parameter '";
293    const ParmVarDecl *PVD = (*CE)->parameters()[*Idx];
294    PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
295                              /*Qualified=*/false);
296    os << "'";
297
298    QualType RT = (*CE)->getResultType();
299    if (!RT.isNull() && !RT->isVoidType()) {
300      SVal RV = (*CE)->getReturnValue();
301      if (CurrSt->isNull(RV).isConstrainedTrue()) {
302        os << " (assuming the call returns zero)";
303      } else if (CurrSt->isNonNull(RV).isConstrainedTrue()) {
304        os << " (assuming the call returns non-zero)";
305      }
306
307    }
308  }
309}
310
311namespace clang {
312namespace ento {
313namespace retaincountchecker {
314
315class RefCountReportVisitor : public BugReporterVisitor {
316protected:
317  SymbolRef Sym;
318
319public:
320  RefCountReportVisitor(SymbolRef sym) : Sym(sym) {}
321
322  void Profile(llvm::FoldingSetNodeID &ID) const override {
323    static int x = 0;
324    ID.AddPointer(&x);
325    ID.AddPointer(Sym);
326  }
327
328  PathDiagnosticPieceRef VisitNode(const ExplodedNode *N,
329                                   BugReporterContext &BRC,
330                                   PathSensitiveBugReport &BR) override;
331
332  PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
333                                    const ExplodedNode *N,
334                                    PathSensitiveBugReport &BR) override;
335};
336
337class RefLeakReportVisitor : public RefCountReportVisitor {
338public:
339  RefLeakReportVisitor(SymbolRef sym) : RefCountReportVisitor(sym) {}
340
341  PathDiagnosticPieceRef getEndPath(BugReporterContext &BRC,
342                                    const ExplodedNode *N,
343                                    PathSensitiveBugReport &BR) override;
344};
345
346} // end namespace retaincountchecker
347} // end namespace ento
348} // end namespace clang
349
350
351/// Find the first node with the parent stack frame.
352static const ExplodedNode *getCalleeNode(const ExplodedNode *Pred) {
353  const StackFrameContext *SC = Pred->getStackFrame();
354  if (SC->inTopFrame())
355    return nullptr;
356  const StackFrameContext *PC = SC->getParent()->getStackFrame();
357  if (!PC)
358    return nullptr;
359
360  const ExplodedNode *N = Pred;
361  while (N && N->getStackFrame() != PC) {
362    N = N->getFirstPred();
363  }
364  return N;
365}
366
367
368/// Insert a diagnostic piece at function exit
369/// if a function parameter is annotated as "os_consumed",
370/// but it does not actually consume the reference.
371static std::shared_ptr<PathDiagnosticEventPiece>
372annotateConsumedSummaryMismatch(const ExplodedNode *N,
373                                CallExitBegin &CallExitLoc,
374                                const SourceManager &SM,
375                                CallEventManager &CEMgr) {
376
377  const ExplodedNode *CN = getCalleeNode(N);
378  if (!CN)
379    return nullptr;
380
381  CallEventRef<> Call = CEMgr.getCaller(N->getStackFrame(), N->getState());
382
383  std::string sbuf;
384  llvm::raw_string_ostream os(sbuf);
385  ArrayRef<const ParmVarDecl *> Parameters = Call->parameters();
386  for (unsigned I=0; I < Call->getNumArgs() && I < Parameters.size(); ++I) {
387    const ParmVarDecl *PVD = Parameters[I];
388
389    if (!PVD->hasAttr<OSConsumedAttr>())
390      continue;
391
392    if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {
393      const RefVal *CountBeforeCall = getRefBinding(CN->getState(), SR);
394      const RefVal *CountAtExit = getRefBinding(N->getState(), SR);
395
396      if (!CountBeforeCall || !CountAtExit)
397        continue;
398
399      unsigned CountBefore = CountBeforeCall->getCount();
400      unsigned CountAfter = CountAtExit->getCount();
401
402      bool AsExpected = CountBefore > 0 && CountAfter == CountBefore - 1;
403      if (!AsExpected) {
404        os << "Parameter '";
405        PVD->getNameForDiagnostic(os, PVD->getASTContext().getPrintingPolicy(),
406                                  /*Qualified=*/false);
407        os << "' is marked as consuming, but the function did not consume "
408           << "the reference\n";
409      }
410    }
411  }
412
413  if (os.str().empty())
414    return nullptr;
415
416  PathDiagnosticLocation L = PathDiagnosticLocation::create(CallExitLoc, SM);
417  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
418}
419
420/// Annotate the parameter at the analysis entry point.
421static std::shared_ptr<PathDiagnosticEventPiece>
422annotateStartParameter(const ExplodedNode *N, SymbolRef Sym,
423                       const SourceManager &SM) {
424  auto PP = N->getLocationAs<BlockEdge>();
425  if (!PP)
426    return nullptr;
427
428  const CFGBlock *Src = PP->getSrc();
429  const RefVal *CurrT = getRefBinding(N->getState(), Sym);
430
431  if (&Src->getParent()->getEntry() != Src || !CurrT ||
432      getRefBinding(N->getFirstPred()->getState(), Sym))
433    return nullptr;
434
435  const auto *VR = cast<VarRegion>(cast<SymbolRegionValue>(Sym)->getRegion());
436  const auto *PVD = cast<ParmVarDecl>(VR->getDecl());
437  PathDiagnosticLocation L = PathDiagnosticLocation(PVD, SM);
438
439  std::string s;
440  llvm::raw_string_ostream os(s);
441  os << "Parameter '" << PVD->getNameAsString() << "' starts at +";
442  if (CurrT->getCount() == 1) {
443    os << "1, as it is marked as consuming";
444  } else {
445    assert(CurrT->getCount() == 0);
446    os << "0";
447  }
448  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
449}
450
451PathDiagnosticPieceRef
452RefCountReportVisitor::VisitNode(const ExplodedNode *N, BugReporterContext &BRC,
453                                 PathSensitiveBugReport &BR) {
454
455  const auto &BT = static_cast<const RefCountBug&>(BR.getBugType());
456  const auto *Checker =
457      static_cast<const RetainCountChecker *>(BT.getChecker());
458
459  bool IsFreeUnowned = BT.getBugType() == RefCountBug::FreeNotOwned ||
460                       BT.getBugType() == RefCountBug::DeallocNotOwned;
461
462  const SourceManager &SM = BRC.getSourceManager();
463  CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
464  if (auto CE = N->getLocationAs<CallExitBegin>())
465    if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr))
466      return PD;
467
468  if (auto PD = annotateStartParameter(N, Sym, SM))
469    return PD;
470
471  // FIXME: We will eventually need to handle non-statement-based events
472  // (__attribute__((cleanup))).
473  if (!N->getLocation().getAs<StmtPoint>())
474    return nullptr;
475
476  // Check if the type state has changed.
477  const ExplodedNode *PrevNode = N->getFirstPred();
478  ProgramStateRef PrevSt = PrevNode->getState();
479  ProgramStateRef CurrSt = N->getState();
480  const LocationContext *LCtx = N->getLocationContext();
481
482  const RefVal* CurrT = getRefBinding(CurrSt, Sym);
483  if (!CurrT)
484    return nullptr;
485
486  const RefVal &CurrV = *CurrT;
487  const RefVal *PrevT = getRefBinding(PrevSt, Sym);
488
489  // Create a string buffer to constain all the useful things we want
490  // to tell the user.
491  std::string sbuf;
492  llvm::raw_string_ostream os(sbuf);
493
494  if (PrevT && IsFreeUnowned && CurrV.isNotOwned() && PrevT->isOwned()) {
495    os << "Object is now not exclusively owned";
496    auto Pos = PathDiagnosticLocation::create(N->getLocation(), SM);
497    return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
498  }
499
500  // This is the allocation site since the previous node had no bindings
501  // for this symbol.
502  if (!PrevT) {
503    const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
504
505    if (isa<ObjCIvarRefExpr>(S) &&
506        isSynthesizedAccessor(LCtx->getStackFrame())) {
507      S = LCtx->getStackFrame()->getCallSite();
508    }
509
510    if (isa<ObjCArrayLiteral>(S)) {
511      os << "NSArray literal is an object with a +0 retain count";
512    } else if (isa<ObjCDictionaryLiteral>(S)) {
513      os << "NSDictionary literal is an object with a +0 retain count";
514    } else if (const ObjCBoxedExpr *BL = dyn_cast<ObjCBoxedExpr>(S)) {
515      if (isNumericLiteralExpression(BL->getSubExpr()))
516        os << "NSNumber literal is an object with a +0 retain count";
517      else {
518        const ObjCInterfaceDecl *BoxClass = nullptr;
519        if (const ObjCMethodDecl *Method = BL->getBoxingMethod())
520          BoxClass = Method->getClassInterface();
521
522        // We should always be able to find the boxing class interface,
523        // but consider this future-proofing.
524        if (BoxClass) {
525          os << *BoxClass << " b";
526        } else {
527          os << "B";
528        }
529
530        os << "oxed expression produces an object with a +0 retain count";
531      }
532    } else if (isa<ObjCIvarRefExpr>(S)) {
533      os << "Object loaded from instance variable";
534    } else {
535      generateDiagnosticsForCallLike(CurrSt, LCtx, CurrV, Sym, S, os);
536    }
537
538    PathDiagnosticLocation Pos(S, SM, N->getLocationContext());
539    return std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
540  }
541
542  // Gather up the effects that were performed on the object at this
543  // program point
544  bool DeallocSent = false;
545
546  const ProgramPointTag *Tag = N->getLocation().getTag();
547
548  if (Tag == &Checker->getCastFailTag()) {
549    os << "Assuming dynamic cast returns null due to type mismatch";
550  }
551
552  if (Tag == &Checker->getDeallocSentTag()) {
553    // We only have summaries attached to nodes after evaluating CallExpr and
554    // ObjCMessageExprs.
555    const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
556
557    if (const CallExpr *CE = dyn_cast<CallExpr>(S)) {
558      // Iterate through the parameter expressions and see if the symbol
559      // was ever passed as an argument.
560      unsigned i = 0;
561
562      for (auto AI=CE->arg_begin(), AE=CE->arg_end(); AI!=AE; ++AI, ++i) {
563
564        // Retrieve the value of the argument.  Is it the symbol
565        // we are interested in?
566        if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym)
567          continue;
568
569        // We have an argument.  Get the effect!
570        DeallocSent = true;
571      }
572    } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) {
573      if (const Expr *receiver = ME->getInstanceReceiver()) {
574        if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx)
575              .getAsLocSymbol() == Sym) {
576          // The symbol we are tracking is the receiver.
577          DeallocSent = true;
578        }
579      }
580    }
581  }
582
583  if (!shouldGenerateNote(os, PrevT, CurrV, DeallocSent))
584    return nullptr;
585
586  if (os.str().empty())
587    return nullptr; // We have nothing to say!
588
589  const Stmt *S = N->getLocation().castAs<StmtPoint>().getStmt();
590  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
591                                N->getLocationContext());
592  auto P = std::make_shared<PathDiagnosticEventPiece>(Pos, os.str());
593
594  // Add the range by scanning the children of the statement for any bindings
595  // to Sym.
596  for (const Stmt *Child : S->children())
597    if (const Expr *Exp = dyn_cast_or_null<Expr>(Child))
598      if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) {
599        P->addRange(Exp->getSourceRange());
600        break;
601      }
602
603  return std::move(P);
604}
605
606static Optional<std::string> describeRegion(const MemRegion *MR) {
607  if (const auto *VR = dyn_cast_or_null<VarRegion>(MR))
608    return std::string(VR->getDecl()->getName());
609  // Once we support more storage locations for bindings,
610  // this would need to be improved.
611  return None;
612}
613
614namespace {
615// Find the first node in the current function context that referred to the
616// tracked symbol and the memory location that value was stored to. Note, the
617// value is only reported if the allocation occurred in the same function as
618// the leak. The function can also return a location context, which should be
619// treated as interesting.
620struct AllocationInfo {
621  const ExplodedNode* N;
622  const MemRegion *R;
623  const LocationContext *InterestingMethodContext;
624  AllocationInfo(const ExplodedNode *InN,
625                 const MemRegion *InR,
626                 const LocationContext *InInterestingMethodContext) :
627    N(InN), R(InR), InterestingMethodContext(InInterestingMethodContext) {}
628};
629} // end anonymous namespace
630
631static AllocationInfo GetAllocationSite(ProgramStateManager &StateMgr,
632                                        const ExplodedNode *N, SymbolRef Sym) {
633  const ExplodedNode *AllocationNode = N;
634  const ExplodedNode *AllocationNodeInCurrentOrParentContext = N;
635  const MemRegion *FirstBinding = nullptr;
636  const LocationContext *LeakContext = N->getLocationContext();
637
638  // The location context of the init method called on the leaked object, if
639  // available.
640  const LocationContext *InitMethodContext = nullptr;
641
642  while (N) {
643    ProgramStateRef St = N->getState();
644    const LocationContext *NContext = N->getLocationContext();
645
646    if (!getRefBinding(St, Sym))
647      break;
648
649    StoreManager::FindUniqueBinding FB(Sym);
650    StateMgr.iterBindings(St, FB);
651
652    if (FB) {
653      const MemRegion *R = FB.getRegion();
654      // Do not show local variables belonging to a function other than
655      // where the error is reported.
656      if (auto MR = dyn_cast<StackSpaceRegion>(R->getMemorySpace()))
657        if (MR->getStackFrame() == LeakContext->getStackFrame())
658          FirstBinding = R;
659    }
660
661    // AllocationNode is the last node in which the symbol was tracked.
662    AllocationNode = N;
663
664    // AllocationNodeInCurrentContext, is the last node in the current or
665    // parent context in which the symbol was tracked.
666    //
667    // Note that the allocation site might be in the parent context. For example,
668    // the case where an allocation happens in a block that captures a reference
669    // to it and that reference is overwritten/dropped by another call to
670    // the block.
671    if (NContext == LeakContext || NContext->isParentOf(LeakContext))
672      AllocationNodeInCurrentOrParentContext = N;
673
674    // Find the last init that was called on the given symbol and store the
675    // init method's location context.
676    if (!InitMethodContext)
677      if (auto CEP = N->getLocation().getAs<CallEnter>()) {
678        const Stmt *CE = CEP->getCallExpr();
679        if (const auto *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
680          const Stmt *RecExpr = ME->getInstanceReceiver();
681          if (RecExpr) {
682            SVal RecV = St->getSVal(RecExpr, NContext);
683            if (ME->getMethodFamily() == OMF_init && RecV.getAsSymbol() == Sym)
684              InitMethodContext = CEP->getCalleeContext();
685          }
686        }
687      }
688
689    N = N->getFirstPred();
690  }
691
692  // If we are reporting a leak of the object that was allocated with alloc,
693  // mark its init method as interesting.
694  const LocationContext *InterestingMethodContext = nullptr;
695  if (InitMethodContext) {
696    const ProgramPoint AllocPP = AllocationNode->getLocation();
697    if (Optional<StmtPoint> SP = AllocPP.getAs<StmtPoint>())
698      if (const ObjCMessageExpr *ME = SP->getStmtAs<ObjCMessageExpr>())
699        if (ME->getMethodFamily() == OMF_alloc)
700          InterestingMethodContext = InitMethodContext;
701  }
702
703  // If allocation happened in a function different from the leak node context,
704  // do not report the binding.
705  assert(N && "Could not find allocation node");
706
707  if (AllocationNodeInCurrentOrParentContext &&
708      AllocationNodeInCurrentOrParentContext->getLocationContext() !=
709      LeakContext)
710    FirstBinding = nullptr;
711
712  return AllocationInfo(AllocationNodeInCurrentOrParentContext, FirstBinding,
713                        InterestingMethodContext);
714}
715
716PathDiagnosticPieceRef
717RefCountReportVisitor::getEndPath(BugReporterContext &BRC,
718                                  const ExplodedNode *EndN,
719                                  PathSensitiveBugReport &BR) {
720  BR.markInteresting(Sym);
721  return BugReporterVisitor::getDefaultEndPath(BRC, EndN, BR);
722}
723
724PathDiagnosticPieceRef
725RefLeakReportVisitor::getEndPath(BugReporterContext &BRC,
726                                 const ExplodedNode *EndN,
727                                 PathSensitiveBugReport &BR) {
728
729  // Tell the BugReporterContext to report cases when the tracked symbol is
730  // assigned to different variables, etc.
731  BR.markInteresting(Sym);
732
733  // We are reporting a leak.  Walk up the graph to get to the first node where
734  // the symbol appeared, and also get the first VarDecl that tracked object
735  // is stored to.
736  AllocationInfo AllocI = GetAllocationSite(BRC.getStateManager(), EndN, Sym);
737
738  const MemRegion* FirstBinding = AllocI.R;
739  BR.markInteresting(AllocI.InterestingMethodContext);
740
741  PathDiagnosticLocation L = cast<RefLeakReport>(BR).getEndOfPath();
742
743  std::string sbuf;
744  llvm::raw_string_ostream os(sbuf);
745
746  os << "Object leaked: ";
747
748  Optional<std::string> RegionDescription = describeRegion(FirstBinding);
749  if (RegionDescription) {
750    os << "object allocated and stored into '" << *RegionDescription << '\'';
751  } else {
752    os << "allocated object of type '" << getPrettyTypeName(Sym->getType())
753       << "'";
754  }
755
756  // Get the retain count.
757  const RefVal* RV = getRefBinding(EndN->getState(), Sym);
758  assert(RV);
759
760  if (RV->getKind() == RefVal::ErrorLeakReturned) {
761    // FIXME: Per comments in rdar://6320065, "create" only applies to CF
762    // objects.  Only "copy", "alloc", "retain" and "new" transfer ownership
763    // to the caller for NS objects.
764    const Decl *D = &EndN->getCodeDecl();
765
766    os << (isa<ObjCMethodDecl>(D) ? " is returned from a method "
767                                  : " is returned from a function ");
768
769    if (D->hasAttr<CFReturnsNotRetainedAttr>()) {
770      os << "that is annotated as CF_RETURNS_NOT_RETAINED";
771    } else if (D->hasAttr<NSReturnsNotRetainedAttr>()) {
772      os << "that is annotated as NS_RETURNS_NOT_RETAINED";
773    } else if (D->hasAttr<OSReturnsNotRetainedAttr>()) {
774      os << "that is annotated as OS_RETURNS_NOT_RETAINED";
775    } else {
776      if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
777        if (BRC.getASTContext().getLangOpts().ObjCAutoRefCount) {
778          os << "managed by Automatic Reference Counting";
779        } else {
780          os << "whose name ('" << MD->getSelector().getAsString()
781             << "') does not start with "
782                "'copy', 'mutableCopy', 'alloc' or 'new'."
783                "  This violates the naming convention rules"
784                " given in the Memory Management Guide for Cocoa";
785        }
786      } else {
787        const FunctionDecl *FD = cast<FunctionDecl>(D);
788        ObjKind K = RV->getObjKind();
789        if (K == ObjKind::ObjC || K == ObjKind::CF) {
790          os << "whose name ('" << *FD
791             << "') does not contain 'Copy' or 'Create'.  This violates the "
792                "naming"
793                " convention rules given in the Memory Management Guide for "
794                "Core"
795                " Foundation";
796        } else if (RV->getObjKind() == ObjKind::OS) {
797          std::string FuncName = FD->getNameAsString();
798          os << "whose name ('" << FuncName
799            << "') starts with '" << StringRef(FuncName).substr(0, 3) << "'";
800        }
801      }
802    }
803  } else {
804    os << " is not referenced later in this execution path and has a retain "
805          "count of +" << RV->getCount();
806  }
807
808  return std::make_shared<PathDiagnosticEventPiece>(L, os.str());
809}
810
811RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
812                               ExplodedNode *n, SymbolRef sym, bool isLeak)
813    : PathSensitiveBugReport(D, D.getDescription(), n), Sym(sym),
814      isLeak(isLeak) {
815  if (!isLeak)
816    addVisitor(std::make_unique<RefCountReportVisitor>(sym));
817}
818
819RefCountReport::RefCountReport(const RefCountBug &D, const LangOptions &LOpts,
820                               ExplodedNode *n, SymbolRef sym,
821                               StringRef endText)
822    : PathSensitiveBugReport(D, D.getDescription(), endText, n) {
823
824  addVisitor(std::make_unique<RefCountReportVisitor>(sym));
825}
826
827void RefLeakReport::deriveParamLocation(CheckerContext &Ctx, SymbolRef sym) {
828  const SourceManager& SMgr = Ctx.getSourceManager();
829
830  if (!sym->getOriginRegion())
831    return;
832
833  auto *Region = dyn_cast<DeclRegion>(sym->getOriginRegion());
834  if (Region) {
835    const Decl *PDecl = Region->getDecl();
836    if (PDecl && isa<ParmVarDecl>(PDecl)) {
837      PathDiagnosticLocation ParamLocation =
838          PathDiagnosticLocation::create(PDecl, SMgr);
839      Location = ParamLocation;
840      UniqueingLocation = ParamLocation;
841      UniqueingDecl = Ctx.getLocationContext()->getDecl();
842    }
843  }
844}
845
846void RefLeakReport::deriveAllocLocation(CheckerContext &Ctx,
847                                          SymbolRef sym) {
848  // Most bug reports are cached at the location where they occurred.
849  // With leaks, we want to unique them by the location where they were
850  // allocated, and only report a single path.  To do this, we need to find
851  // the allocation site of a piece of tracked memory, which we do via a
852  // call to GetAllocationSite.  This will walk the ExplodedGraph backwards.
853  // Note that this is *not* the trimmed graph; we are guaranteed, however,
854  // that all ancestor nodes that represent the allocation site have the
855  // same SourceLocation.
856  const ExplodedNode *AllocNode = nullptr;
857
858  const SourceManager& SMgr = Ctx.getSourceManager();
859
860  AllocationInfo AllocI =
861      GetAllocationSite(Ctx.getStateManager(), getErrorNode(), sym);
862
863  AllocNode = AllocI.N;
864  AllocBinding = AllocI.R;
865  markInteresting(AllocI.InterestingMethodContext);
866
867  // Get the SourceLocation for the allocation site.
868  // FIXME: This will crash the analyzer if an allocation comes from an
869  // implicit call (ex: a destructor call).
870  // (Currently there are no such allocations in Cocoa, though.)
871  AllocStmt = AllocNode->getStmtForDiagnostics();
872
873  if (!AllocStmt) {
874    AllocBinding = nullptr;
875    return;
876  }
877
878  PathDiagnosticLocation AllocLocation =
879    PathDiagnosticLocation::createBegin(AllocStmt, SMgr,
880                                        AllocNode->getLocationContext());
881  Location = AllocLocation;
882
883  // Set uniqieing info, which will be used for unique the bug reports. The
884  // leaks should be uniqued on the allocation site.
885  UniqueingLocation = AllocLocation;
886  UniqueingDecl = AllocNode->getLocationContext()->getDecl();
887}
888
889void RefLeakReport::createDescription(CheckerContext &Ctx) {
890  assert(Location.isValid() && UniqueingDecl && UniqueingLocation.isValid());
891  Description.clear();
892  llvm::raw_string_ostream os(Description);
893  os << "Potential leak of an object";
894
895  Optional<std::string> RegionDescription = describeRegion(AllocBinding);
896  if (RegionDescription) {
897    os << " stored into '" << *RegionDescription << '\'';
898  } else {
899
900    // If we can't figure out the name, just supply the type information.
901    os << " of type '" << getPrettyTypeName(Sym->getType()) << "'";
902  }
903}
904
905RefLeakReport::RefLeakReport(const RefCountBug &D, const LangOptions &LOpts,
906                             ExplodedNode *n, SymbolRef sym,
907                             CheckerContext &Ctx)
908    : RefCountReport(D, LOpts, n, sym, /*isLeak=*/true) {
909
910  deriveAllocLocation(Ctx, sym);
911  if (!AllocBinding)
912    deriveParamLocation(Ctx, sym);
913
914  createDescription(Ctx);
915
916  addVisitor(std::make_unique<RefLeakReportVisitor>(sym));
917}
918