r180234 - [analyzer] Fix a crash in RetainCountChecker - we should not rely on CallEnter::getCallExpr to return non-NULL
Anna Zaks
ganna at apple.com
Wed Apr 24 17:41:33 PDT 2013
Author: zaks
Date: Wed Apr 24 19:41:32 2013
New Revision: 180234
URL: http://llvm.org/viewvc/llvm-project?rev=180234&view=rev
Log:
[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!)
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
cfe/trunk/test/Analysis/retain-release.mm
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=180234&r1=180233&r2=180234&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Wed Apr 24 19:41:32 2013
@@ -2192,7 +2192,7 @@ GetAllocationSite(ProgramStateManager& S
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);
Modified: cfe/trunk/test/Analysis/retain-release.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.mm?rev=180234&r1=180233&r2=180234&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.mm (original)
+++ cfe/trunk/test/Analysis/retain-release.mm Wed Apr 24 19:41:32 2013
@@ -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(
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}}
+ }
+}
+
More information about the cfe-commits
mailing list