[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