]> granicus.if.org Git - clang/commitdiff
retain/release checker: Recognize that calls to
authorTed Kremenek <kremenek@apple.com>
Wed, 14 Oct 2009 00:27:24 +0000 (00:27 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 14 Oct 2009 00:27:24 +0000 (00:27 +0000)
'CVPixelBufferCreateWithPlanarBytes()' and
'CVPixelBufferCreateWithBytes' (Core Video API) can indirectly release
a pixel buffer object via a callback.

This fixes <rdar://problem/7283567>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@84064 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/CFRefCount.cpp
test/Analysis/retain-release.m

index 3a4120c642b1f344dca8cb6d34bd45a738606f54..9b6125705d9aa9a00b870e31b129a74dc1180fb6 100644 (file)
@@ -967,8 +967,8 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
 
     // FIXME: This should all be refactored into a chain of "summary lookup"
     //  filters.
-    assert (ScratchArgs.isEmpty());
-
+    assert(ScratchArgs.isEmpty());
+    
     switch (strlen(FName)) {
       default: break;
       case 14:
@@ -1046,7 +1046,17 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
           // This should be addressed using a API table.  This strcmp is also
           // a little gross, but there is no need to super optimize here.
           ScratchArgs = AF.Add(ScratchArgs, 1, DecRef);
-          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
+                                   DoNothing);
+        }
+        else if (!memcmp(FName, "CVPixelBufferCreateWithBytes", 28)) {
+          // FIXES: <rdar://problem/7283567>
+          // Eventually this can be improved by recognizing that the pixel
+          // buffer passed to CVPixelBufferCreateWithBytes is released via
+          // a callback and doing full IPA to make sure this is done correctly.
+          ScratchArgs = AF.Add(ScratchArgs, 7, StopTracking);
+          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
+                                   DoNothing);
         }
         break;
 
@@ -1058,6 +1068,19 @@ RetainSummary* RetainSummaryManager::getSummary(FunctionDecl* FD) {
           S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
         }
         break;
+        
+      case 34:
+        if (!memcmp(FName, "CVPixelBufferCreateWithPlanarBytes", 34)) {
+          // FIXES: <rdar://problem/7283567>
+          // Eventually this can be improved by recognizing that the pixel
+          // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
+          // via a callback and doing full IPA to make sure this is done
+          // correctly.
+          ScratchArgs = AF.Add(ScratchArgs, 12, StopTracking);
+          S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing,
+                                   DoNothing);
+        }
+        break;
     }
 
     // Did we get a summary?
index abda7535389f826f4b9782b76b67437935555537..7076bb294254214ff82f39d9257b784ca5acfea7 100644 (file)
@@ -997,6 +997,106 @@ void rdar_7299394_positive(pthread_attr_t *attr, pthread_t *thread) {
   NSNumber *number = [[NSNumber alloc] initWithInt:5]; // expected-warning{{leak}}
 }
 
+//===----------------------------------------------------------------------===//
+// <rdar://problem/7283567> False leak associated with call to 
+//                          CVPixelBufferCreateWithBytes ()
+//
+// According to the Core Video Reference (ADC), CVPixelBufferCreateWithBytes and
+// CVPixelBufferCreateWithPlanarBytes can release (via a callback) the
+// pixel buffer object.  These test cases show how the analyzer stops tracking
+// the reference count for the objects passed for this argument.  This
+// could be made smarter.
+//===----------------------------------------------------------------------===//
+
+typedef int int32_t;
+typedef UInt32 FourCharCode;
+typedef FourCharCode OSType;
+typedef uint64_t CVOptionFlags;
+typedef int32_t CVReturn;
+typedef struct __CVBuffer *CVBufferRef;
+typedef CVBufferRef CVImageBufferRef;
+typedef CVImageBufferRef CVPixelBufferRef;
+typedef void (*CVPixelBufferReleaseBytesCallback)( void *releaseRefCon, const void *baseAddress );
+
+extern CVReturn CVPixelBufferCreateWithBytes(CFAllocatorRef allocator,
+            size_t width,
+            size_t height,
+            OSType pixelFormatType,
+            void *baseAddress,
+            size_t bytesPerRow,
+            CVPixelBufferReleaseBytesCallback releaseCallback,
+            void *releaseRefCon,
+            CFDictionaryRef pixelBufferAttributes,
+                   CVPixelBufferRef *pixelBufferOut) ;
+
+typedef void (*CVPixelBufferReleasePlanarBytesCallback)( void *releaseRefCon, const void *dataPtr, size_t dataSize, size_t numberOfPlanes, const void *planeAddresses[] );
+
+extern CVReturn CVPixelBufferCreateWithPlanarBytes(CFAllocatorRef allocator,
+        size_t width,
+        size_t height,
+        OSType pixelFormatType,
+        void *dataPtr,
+        size_t dataSize,
+        size_t numberOfPlanes,
+        void *planeBaseAddress[],
+        size_t planeWidth[],
+        size_t planeHeight[],
+        size_t planeBytesPerRow[],
+        CVPixelBufferReleasePlanarBytesCallback releaseCallback,
+        void *releaseRefCon,
+        CFDictionaryRef pixelBufferAttributes,
+        CVPixelBufferRef *pixelBufferOut) ;
+
+extern CVReturn CVPixelBufferCreateWithBytes(CFAllocatorRef allocator,
+            size_t width,
+            size_t height,
+            OSType pixelFormatType,
+            void *baseAddress,
+            size_t bytesPerRow,
+            CVPixelBufferReleaseBytesCallback releaseCallback,
+            void *releaseRefCon,
+            CFDictionaryRef pixelBufferAttributes,
+                   CVPixelBufferRef *pixelBufferOut) ;
+
+CVReturn rdar_7283567(CFAllocatorRef allocator, size_t width, size_t height,
+                      OSType pixelFormatType, void *baseAddress,
+                      size_t bytesPerRow,
+                      CVPixelBufferReleaseBytesCallback releaseCallback,
+                      CFDictionaryRef pixelBufferAttributes,
+                      CVPixelBufferRef *pixelBufferOut) {
+
+  // For the allocated object, it doesn't really matter what type it is
+  // for the purpose of this test.  All we want to show is that
+  // this is freed later by the callback.
+  NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
+  
+  return CVPixelBufferCreateWithBytes(allocator, width, height, pixelFormatType,
+                                baseAddress, bytesPerRow, releaseCallback,
+                                number, // potentially released by callback
+                                pixelBufferAttributes, pixelBufferOut) ;
+}
+
+CVReturn rdar_7283567_2(CFAllocatorRef allocator, size_t width, size_t height,
+        OSType pixelFormatType, void *dataPtr, size_t dataSize,
+        size_t numberOfPlanes, void *planeBaseAddress[],
+        size_t planeWidth[], size_t planeHeight[], size_t planeBytesPerRow[],
+        CVPixelBufferReleasePlanarBytesCallback releaseCallback,
+        CFDictionaryRef pixelBufferAttributes,
+        CVPixelBufferRef *pixelBufferOut) {
+    
+    // For the allocated object, it doesn't really matter what type it is
+    // for the purpose of this test.  All we want to show is that
+    // this is freed later by the callback.
+    NSNumber *number = [[NSNumber alloc] initWithInt:5]; // no-warning
+
+    return CVPixelBufferCreateWithPlanarBytes(allocator,
+              width, height, pixelFormatType, dataPtr, dataSize,
+              numberOfPlanes, planeBaseAddress, planeWidth,
+              planeHeight, planeBytesPerRow, releaseCallback,
+              number, // potentially released by callback
+              pixelBufferAttributes, pixelBufferOut) ;
+}
+
 //===----------------------------------------------------------------------===//
 // Tests of ownership attributes.
 //===----------------------------------------------------------------------===//