retain/release checker: Recognize that calls to

'CVPixelBufferCreateWithPlanarBytes()' and
'CVPixelBufferCreateWithBytes' (Core Video API) can indirectly release
a pixel buffer object via a callback.

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

llvm-svn: 84064
This commit is contained in:
Ted Kremenek 2009-10-14 00:27:24 +00:00
parent dd1e23b72b
commit b4ec3fc42d
2 changed files with 126 additions and 3 deletions

View 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?

View 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.
//===----------------------------------------------------------------------===//