aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/StaticAnalyzer/Checkers/MallocChecker.cpp12
-rw-r--r--test/Analysis/malloc.c19
-rw-r--r--test/Analysis/system-header-simulator.h7
3 files changed, 33 insertions, 5 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
index c22c6a2687..1adcca03fd 100644
--- a/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1334,12 +1334,14 @@ bool MallocChecker::doesNotFreeMemory(const CallOrObjCMessage *Call,
return false;
}
- // A bunch of other functions, which take ownership of a pointer (See retain
- // release checker). Not all the parameters here are invalidated, but the
- // Malloc checker cannot differentiate between them. The right way of doing
- // this would be to implement a pointer escapes callback.
- if (FName == "CVPixelBufferCreateWithBytes" ||
+ // A bunch of other functions which either take ownership of a pointer or
+ // wrap the result up in a struct or object, meaning it can be freed later.
+ // (See RetainCountChecker.) Not all the parameters here are invalidated,
+ // but the Malloc checker cannot differentiate between them. The right way
+ // of doing this would be to implement a pointer escapes callback.
+ if (FName == "CGBitmapContextCreate" ||
FName == "CGBitmapContextCreateWithData" ||
+ FName == "CVPixelBufferCreateWithBytes" ||
FName == "CVPixelBufferCreateWithPlanarBytes" ||
FName == "OSAtomicEnqueue") {
return false;
diff --git a/test/Analysis/malloc.c b/test/Analysis/malloc.c
index 7c2196ac9e..c532d6813f 100644
--- a/test/Analysis/malloc.c
+++ b/test/Analysis/malloc.c
@@ -955,3 +955,22 @@ void test_double_assign_ints_positive()
(void*)(long)(unsigned long)ptr; // expected-warning {{unused}} expected-warning {{leak}}
}
+
+void testCGContextNoLeak()
+{
+ void *ptr = malloc(16);
+ CGContextRef context = CGBitmapContextCreate(ptr);
+
+ // Because you can get the data back out like this, even much later,
+ // CGBitmapContextCreate is one of our "stop-tracking" exceptions.
+ free(CGBitmapContextGetData(context));
+}
+
+void testCGContextLeak()
+{
+ void *ptr = malloc(16);
+ CGContextRef context = CGBitmapContextCreate(ptr);
+ // However, this time we're just leaking the data, because the context
+ // object doesn't escape and it hasn't been freed in this function.
+}
+
diff --git a/test/Analysis/system-header-simulator.h b/test/Analysis/system-header-simulator.h
index a8cba9ce5b..d2fb2e8684 100644
--- a/test/Analysis/system-header-simulator.h
+++ b/test/Analysis/system-header-simulator.h
@@ -46,3 +46,10 @@ typedef struct {
int dealocateMemWhenDoneByVal(void*, StWithCallback);
int dealocateMemWhenDoneByRef(StWithCallback*, const void*);
+
+typedef struct CGContext *CGContextRef;
+CGContextRef CGBitmapContextCreate(void *data/*, size_t width, size_t height,
+ size_t bitsPerComponent, size_t bytesPerRow,
+ CGColorSpaceRef space,
+ CGBitmapInfo bitmapInfo*/);
+void *CGBitmapContextGetData(CGContextRef context);