forked from OSchip/llvm-project
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:
parent
dd1e23b72b
commit
b4ec3fc42d
|
@ -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?
|
||||
|
|
|
@ -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.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
Loading…
Reference in New Issue