]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix a crash in RetainCountChecker - we should not rely on CallEnter::getCa...
authorAnna Zaks <ganna@apple.com>
Thu, 25 Apr 2013 00:41:32 +0000 (00:41 +0000)
committerAnna Zaks <ganna@apple.com>
Thu, 25 Apr 2013 00:41:32 +0000 (00:41 +0000)
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

lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
test/Analysis/retain-release.mm

index 824ce34ab33d421aa7a7d77d0dceb86016ba30cc..0d256006e1c7e5062131d12af747dfcded246947 100644 (file)
@@ -2192,7 +2192,7 @@ GetAllocationSite(ProgramStateManager& StateMgr, const ExplodedNode *N,
     if (!InitMethodContext)
       if (Optional<CallEnter> CEP = N->getLocation().getAs<CallEnter>()) {
         const Stmt *CE = CEP->getCallExpr();
-        if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(CE)) {
+        if (const ObjCMessageExpr *ME = dyn_cast_or_null<ObjCMessageExpr>(CE)) {
           const Stmt *RecExpr = ME->getInstanceReceiver();
           if (RecExpr) {
             SVal RecV = St->getSVal(RecExpr, NContext);
index 47d67eae1b9ff4835607651ee70f69f159203d86..3650d887244b91ab59ad545de12fbcc85dfc312c 100644 (file)
@@ -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 <typename X>
+class Holder {
+public:
+       Holder() throw();
+       ~Holder() throw() {}
+       X* get() const throw();
+       void reset(X* p) throw();
+private:
+       X* ptr_;
+};
+
+template<typename X>
+inline
+Holder<X>::Holder() throw()
+: ptr_(0){}
+
+template <typename X>
+inline
+X* Holder<X>::get() const throw() {
+       return ptr_;
+}
+
+template <typename X>
+inline
+void Holder<X>::reset(X* p) throw() {
+       if (ptr_ != p) {
+               if (ptr_ != 0) {
+                       ::CFRelease( ptr_ );
+               }
+               ptr_ = p;
+       }
+}
+
+class radar13722286 {
+public:
+  radar13722286() {}
+private:
+       void                    PrepareBitmap();
+       Holder<const struct __CFString> mStr;
+};
+
+void   radar13722286::PrepareBitmap() {
+       if (mStr.get() != 0) {
+               Holder<const struct __CFString> str1;
+               mStr.reset( CFStringCreateCopy( 0, str1.get() ) ); //expected-warning {{Potential leak of an object}}
+       }
+}
+