r286633 - [analyzer] Teach RetainCountChecker about VTCompressionSessionEncodeFrame()

Devin Coughlin via cfe-commits cfe-commits at lists.llvm.org
Fri Nov 11 13:31:38 PST 2016


Author: dcoughlin
Date: Fri Nov 11 15:31:38 2016
New Revision: 286633

URL: http://llvm.org/viewvc/llvm-project?rev=286633&view=rev
Log:
[analyzer] Teach RetainCountChecker about VTCompressionSessionEncodeFrame()

The context argument passed to VideoToolbox's
VTCompressionSessionEncodeFrame() function is ultimately passed to a callback
supplied when creating the compression session and so may be freed by that
callback.  To suppress false positives in this case, teach the retain count
checker to stop tracking that argument.

This isn't suppressed by the usual callback context mechanism because the call
to VTCompressionSessionEncodeFrame() doesn't include the callback itself.

rdar://problem/27685213

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
    cfe/trunk/test/Analysis/retain-release.m

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp?rev=286633&r1=286632&r2=286633&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp Fri Nov 11 15:31:38 2016
@@ -1126,6 +1126,14 @@ RetainSummaryManager::getFunctionSummary
       // correctly.
       ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
       S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
+    } else if (FName == "VTCompressionSessionEncodeFrame") {
+      // The context argument passed to VTCompressionSessionEncodeFrame()
+      // is passed to the callback specified when creating the session
+      // (e.g. with VTCompressionSessionCreate()) which can release it.
+      // To account for this possibility, conservatively stop tracking
+      // the context.
+      ScratchArgs = AF.add(ScratchArgs, 5, StopTracking);
+      S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, DoNothing);
     } else if (FName == "dispatch_set_context" ||
                FName == "xpc_connection_set_context") {
       // <rdar://problem/11059275> - The analyzer currently doesn't have

Modified: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=286633&r1=286632&r2=286633&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (original)
+++ cfe/trunk/test/Analysis/retain-release.m Fri Nov 11 15:31:38 2016
@@ -1267,6 +1267,88 @@ void testCVPrefixRetain(CMSampleBufferRe
   CVBufferRelease(pixelBufAlias); // no-warning
 }
 
+typedef signed long SInt32;
+typedef SInt32  OSStatus;
+typedef FourCharCode CMVideoCodecType;
+
+
+typedef UInt32 VTEncodeInfoFlags; enum {
+ kVTEncodeInfo_Asynchronous = 1UL << 0,
+ kVTEncodeInfo_FrameDropped = 1UL << 1,
+};
+typedef struct
+{
+  int ignore;
+} CMTime;
+
+
+typedef void (*VTCompressionOutputCallback)(
+    void * _Nullable outputCallbackRefCon,
+    void * _Nullable sourceFrameRefCon,
+    OSStatus status,
+    VTEncodeInfoFlags infoFlags,
+    _Nullable CMSampleBufferRef sampleBuffer );
+
+typedef struct OpaqueVTCompressionSession*  VTCompressionSessionRef;
+
+extern OSStatus
+VTCompressionSessionCreate(_Nullable CFAllocatorRef allocator,
+    int32_t width,
+    int32_t height,
+    CMVideoCodecType codecType,
+    _Nullable CFDictionaryRef encoderSpecification,
+    _Nullable CFDictionaryRef sourceImageBufferAttributes,
+    _Nullable CFAllocatorRef compressedDataAllocator,
+    _Nullable VTCompressionOutputCallback outputCallback,
+    void * _Nullable outputCallbackRefCon,
+    CF_RETURNS_RETAINED _Nullable VTCompressionSessionRef * _Nonnull compressionSessionOut);
+
+extern OSStatus
+VTCompressionSessionEncodeFrame(
+    _Nonnull VTCompressionSessionRef session,
+    _Nonnull CVImageBufferRef imageBuffer,
+    CMTime presentationTimeStamp,
+    CMTime duration,
+    _Nullable CFDictionaryRef frameProperties,
+    void * _Nullable sourceFrameRefCon,
+    VTEncodeInfoFlags * _Nullable infoFlagsOut);
+
+OSStatus test_VTCompressionSessionCreateAndEncode_CallbackReleases(
+    _Nullable CFAllocatorRef allocator,
+    int32_t width,
+    int32_t height,
+    CMVideoCodecType codecType,
+    _Nullable CFDictionaryRef encoderSpecification,
+    _Nullable CFDictionaryRef sourceImageBufferAttributes,
+    _Nullable CFAllocatorRef compressedDataAllocator,
+    _Nullable VTCompressionOutputCallback outputCallback,
+
+    _Nonnull CVImageBufferRef imageBuffer,
+    CMTime presentationTimeStamp,
+    CMTime duration,
+    _Nullable CFDictionaryRef frameProperties
+) {
+
+  // The outputCallback is passed both contexts and so can release either.
+  NSNumber *contextForCreate = [[NSNumber alloc] initWithInt:5]; // no-warning
+  NSNumber *contextForEncode = [[NSNumber alloc] initWithInt:6]; // no-warning
+
+  VTCompressionSessionRef session = 0;
+  OSStatus status = VTCompressionSessionCreate(allocator,
+      width, height, codecType, encoderSpecification,
+      sourceImageBufferAttributes,
+      compressedDataAllocator, outputCallback, contextForCreate,
+      &session);
+
+  VTEncodeInfoFlags encodeInfoFlags;
+
+  status = VTCompressionSessionEncodeFrame(session, imageBuffer,
+      presentationTimeStamp, duration, frameProperties, contextForEncode,
+      &encodeInfoFlags);
+
+  return status;
+}
+
 //===----------------------------------------------------------------------===//
 // <rdar://problem/7358899> False leak associated with 
 //  CGBitmapContextCreateWithData




More information about the cfe-commits mailing list