From 3d8f462d58a4be21f9f5d287253b9b2565506ca5 Mon Sep 17 00:00:00 2001 From: Anna Zaks Date: Thu, 25 Apr 2013 00:41:32 +0000 Subject: [PATCH] [analyzer] Fix a crash in RetainCountChecker - we should not rely on CallEnter::getCallExpr to return non-NULL We get a CallEnter with a null expression, when processing a destructor. All other users of CallEnter::getCallExpr work fine with null as return value. (Addresses PR15832, Thanks to Jordan for reducing the test case!) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180234 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/RetainCountChecker.cpp | 2 +- test/Analysis/retain-release.mm | 55 ++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 824ce34ab3..0d256006e1 100644 --- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -2192,7 +2192,7 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N, if (!InitMethodContext) if (Optional CEP = N->getLocation().getAs()) { const Stmt *CE = CEP->getCallExpr(); - if (const ObjCMessageExpr *ME = dyn_cast(CE)) { + if (const ObjCMessageExpr *ME = dyn_cast_or_null(CE)) { const Stmt *RecExpr = ME->getInstanceReceiver(); if (RecExpr) { SVal RecV = St->getSVal(RecExpr, NContext); diff --git a/test/Analysis/retain-release.mm b/test/Analysis/retain-release.mm index 47d67eae1b..3650d88724 100644 --- a/test/Analysis/retain-release.mm +++ b/test/Analysis/retain-release.mm @@ -83,6 +83,7 @@ typedef UInt32 CFStringEncoding; enum { kCFStringEncodingMacRoman = 0, kCFStringEncodingWindowsLatin1 = 0x0500, kCFStringEncodingISOLatin1 = 0x0201, kCFStringEncodingNextStepLatin = 0x0B01, kCFStringEncodingASCII = 0x0600, kCFStringEncodingUnicode = 0x0100, kCFStringEncodingUTF8 = 0x08000100, kCFStringEncodingNonLossyASCII = 0x0BFF , kCFStringEncodingUTF16 = 0x0100, kCFStringEncodingUTF16BE = 0x10000100, kCFStringEncodingUTF16LE = 0x14000100, kCFStringEncodingUTF32 = 0x0c000100, kCFStringEncodingUTF32BE = 0x18000100, kCFStringEncodingUTF32LE = 0x1c000100 }; extern CFStringRef CFStringCreateWithCString(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding); +extern CFStringRef CFStringCreateCopy(CFAllocatorRef alloc, CFStringRef theString); typedef double CFTimeInterval; typedef CFTimeInterval CFAbsoluteTime; extern CFAbsoluteTime CFAbsoluteTimeGetCurrent(void); @@ -269,7 +270,6 @@ extern void CGContextDrawLinearGradient(CGContextRef context, CGGradientRef gradient, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions options); extern CGColorSpaceRef CGColorSpaceCreateDeviceRGB(void); - //===----------------------------------------------------------------------===// // Test cases. //===----------------------------------------------------------------------===// @@ -408,3 +408,56 @@ void testCallback() { } @end +//===----------------------------------------------------------------------===// +// Don't crash on getting a null expression from CallEnter corresponding to a +// destructor. +//===----------------------------------------------------------------------===// + +template +class Holder { +public: + Holder() throw(); + ~Holder() throw() {} + X* get() const throw(); + void reset(X* p) throw(); +private: + X* ptr_; +}; + +template +inline +Holder::Holder() throw() +: ptr_(0){} + +template +inline +X* Holder::get() const throw() { + return ptr_; +} + +template +inline +void Holder::reset(X* p) throw() { + if (ptr_ != p) { + if (ptr_ != 0) { + ::CFRelease( ptr_ ); + } + ptr_ = p; + } +} + +class radar13722286 { +public: + radar13722286() {} +private: + void PrepareBitmap(); + Holder mStr; +}; + +void radar13722286::PrepareBitmap() { + if (mStr.get() != 0) { + Holder str1; + mStr.reset( CFStringCreateCopy( 0, str1.get() ) ); //expected-warning {{Potential leak of an object}} + } +} + -- 2.40.0