[cfe-commits] r63341 - in /cfe/trunk: lib/Analysis/CFRefCount.cpp test/Analysis/rdar-6539791.c

Ted Kremenek kremenek at apple.com
Thu Jan 29 14:45:13 PST 2009


Author: kremenek
Date: Thu Jan 29 16:45:13 2009
New Revision: 63341

URL: http://llvm.org/viewvc/llvm-project?rev=63341&view=rev
Log:
retain/release checker: When generating summaries for CF/CG functions, allow arguments to "escape" if they are passed to a function containing the terms "InsertValue", "SetValue", or "AddValue".  This fixes <rdar://problem/6539791>.

Added:
    cfe/trunk/test/Analysis/rdar-6539791.c
Modified:
    cfe/trunk/lib/Analysis/CFRefCount.cpp

Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=63341&r1=63340&r2=63341&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Thu Jan 29 16:45:13 2009
@@ -809,12 +809,27 @@
       if (isRelease(FD, FName+2))
         S = getUnarySummary(FT, cfrelease);
       else {
-        // For CoreFoundation and CoreGraphics functions we assume they
-        // follow the ownership idiom strictly and thus do not cause
-        // ownership to "escape".
-        assert (ScratchArgs.empty());  
-        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, 
-                                 DoNothing);
+        assert (ScratchArgs.empty());
+        // Remaining CoreFoundation and CoreGraphics functions.
+        // We use to assume that they all strictly followed the ownership idiom
+        // and that ownership cannot be transferred.  While this is technically
+        // correct, many methods allow a tracked object to escape.  For example:
+        //
+        //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);        
+        //   CFDictionaryAddValue(y, key, x);
+        //   CFRelease(x); 
+        //   ... it is okay to use 'x' since 'y' has a reference to it
+        //
+        // We handle this and similar cases with the follow heuristic.  If the
+        // function name contains "InsertValue", "SetValue" or "AddValue" then
+        // we assume that arguments may "escape."
+        //
+        ArgEffect E = (CStrInCStrNoCase(FName, "InsertValue") ||
+                       CStrInCStrNoCase(FName, "AddValue") ||
+                       CStrInCStrNoCase(FName, "SetValue"))
+                      ? MayEscape : DoNothing;
+        
+        S = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, E);
       }
     }
   }

Added: cfe/trunk/test/Analysis/rdar-6539791.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/rdar-6539791.c?rev=63341&view=auto

==============================================================================
--- cfe/trunk/test/Analysis/rdar-6539791.c (added)
+++ cfe/trunk/test/Analysis/rdar-6539791.c Thu Jan 29 16:45:13 2009
@@ -0,0 +1,31 @@
+// RUN: clang -analyze -checker-cfref -analyzer-store-basic -verify %s &&
+// RUN: clang -analyze -checker-cfref -analyzer-store-region -verify %s
+
+typedef const struct __CFAllocator * CFAllocatorRef;
+typedef struct __CFDictionary * CFMutableDictionaryRef;
+typedef signed long CFIndex;
+typedef CFIndex CFNumberType;
+typedef const void * CFTypeRef;
+typedef struct {} CFDictionaryKeyCallBacks, CFDictionaryValueCallBacks;
+typedef const struct __CFNumber * CFNumberRef;
+extern const CFAllocatorRef kCFAllocatorDefault;
+extern const CFDictionaryKeyCallBacks kCFTypeDictionaryKeyCallBacks;
+extern const CFDictionaryValueCallBacks kCFTypeDictionaryValueCallBacks;
+enum { kCFNumberSInt32Type = 3 };
+CFMutableDictionaryRef CFDictionaryCreateMutable(CFAllocatorRef allocator, CFIndex capacity, const CFDictionaryKeyCallBacks *keyCallBacks, const CFDictionaryValueCallBacks *valueCallBacks);
+void CFDictionaryAddValue(CFMutableDictionaryRef theDict, const void *key, const void *value);
+void CFRelease(CFTypeRef cf);
+extern CFNumberRef CFNumberCreate(CFAllocatorRef allocator, CFNumberType theType, const void *valuePtr);
+
+void f(CFMutableDictionaryRef y, void* key, void* val_key) {
+  CFMutableDictionaryRef x = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+  CFDictionaryAddValue(y, key, x);
+  CFRelease(x); // the dictionary keeps a reference, so the object isn't deallocated yet
+  signed z = 1;
+  CFNumberRef value = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &z);
+  if (value) {
+    CFDictionaryAddValue(x, val_key, value); // no-warning
+    CFRelease(value);
+    CFDictionaryAddValue(y, val_key, value); // no-warning
+  }
+}





More information about the cfe-commits mailing list