RetainCountDiagnostics.cpp 35 KB

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