aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2012-06-19 05:10:32 +0000
committerAnna Zaks <ganna@apple.com>2012-06-19 05:10:32 +0000
commit5f75768579b9b1d70d01903ab4766aede65defcc (patch)
tree2e69b3c0da50cdc99f5abcefb6e897f34bf1a0e1
parentbfcb037a3479de4a453a8275c64ae441c22d43f9 (diff)
[analyzer] Allow pointers to escape into NSPointerArray.
(Fixes radar://11691035 PR13140) git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158703 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp10
-rw-r--r--test/Analysis/malloc.mm23
-rw-r--r--test/Analysis/system-header-simulator-objc.h8
3 files changed, 41 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index 1adcca03fd..255225467f 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1384,6 +1384,16 @@ bool MallocChecker::doesNotFreeMemory(const CallOrObjCMessage *Call,
return false;
}
+ // If the first selector starts with addPointer, insertPointer,
+ // or replacePointer, assume we are dealing with NSPointerArray or similar.
+ // This is similar to C++ containers (vector); we still might want to check
+ // that the pointers get freed, by following the container itself.
+ if (S.getNameForSlot(0).startswith("addPointer") ||
+ S.getNameForSlot(0).startswith("insertPointer") ||
+ S.getNameForSlot(0).startswith("replacePointer")) {
+ return false;
+ }
+
// If the call has a callback as an argument, assume the memory
// can be freed.
if (Call->hasNonZeroCallbackArg())
diff --git a/test/Analysis/malloc.mm b/test/Analysis/malloc.mm
index ef1adda5a1..855892da2b 100644
--- a/test/Analysis/malloc.mm
+++ b/test/Analysis/malloc.mm
@@ -178,4 +178,27 @@ void testCallWithBlockCallback() {
void testCallWithBlockCallbackInSystem() {
void *l = malloc(12);
SystemHeaderFunctionWithBlockParam(l, ^(void *i) { free(i); }, sizeof(char *));
+}
+
+// Test escape into NSPointerArray. radar://11691035, PR13140
+void foo(NSPointerArray* pointerArray) {
+
+ void* p1 = malloc (1024);
+ if (p1) {
+ [pointerArray addPointer:p1];
+ }
+
+ void* p2 = malloc (1024);
+ if (p2) {
+ [pointerArray insertPointer:p2 atIndex:1];
+ }
+
+ void* p3 = malloc (1024);
+ if (p3) {
+ [pointerArray replacePointerAtIndex:1 withPointer:p3];
+ }
+
+ // Freeing the buffer is allowed.
+ void* buffer = [pointerArray pointerAtIndex:0];
+ free(buffer);
} \ No newline at end of file
diff --git a/test/Analysis/system-header-simulator-objc.h b/test/Analysis/system-header-simulator-objc.h
index 4626a4ec4f..20a26cdbaa 100644
--- a/test/Analysis/system-header-simulator-objc.h
+++ b/test/Analysis/system-header-simulator-objc.h
@@ -114,3 +114,11 @@ extern CFStringRef CFStringCreateWithCStringNoCopy(CFAllocatorRef alloc, const c
extern void CFStringAppend(CFMutableStringRef theString, CFStringRef appendedString);
void SystemHeaderFunctionWithBlockParam(void *, void (^block)(void *), unsigned);
+
+@interface NSPointerArray : NSObject <NSFastEnumeration, NSCopying, NSCoding>
+- (void)addPointer:(void *)pointer;
+- (void)insertPointer:(void *)item atIndex:(NSUInteger)index;
+- (void)replacePointerAtIndex:(NSUInteger)index withPointer:(void *)item;
+- (void *)pointerAtIndex:(NSUInteger)index;
+@end
+