aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp6
-rw-r--r--test/Analysis/retain-release-region-store.m7
-rw-r--r--test/Analysis/retain-release.m23
3 files changed, 35 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index 9255796172..a6d33ad2a0 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -3341,6 +3341,12 @@ void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
// the binding).
escapes = (state == (state->bindLoc(*regionLoc, val)));
}
+ if (!escapes) {
+ // Case 4: We do not currently model what happens when a symbol is
+ // assigned to a struct field, so be conservative here and let the symbol
+ // go. TODO: This could definitely be improved upon.
+ escapes = !isa<VarRegion>(regionLoc->getRegion());
+ }
}
// If our store can represent the binding and we aren't storing to something
diff --git a/test/Analysis/retain-release-region-store.m b/test/Analysis/retain-release-region-store.m
index 1ff31b710d..917381341a 100644
--- a/test/Analysis/retain-release-region-store.m
+++ b/test/Analysis/retain-release-region-store.m
@@ -100,6 +100,10 @@ struct foo {
NSDate* f;
};
+// FIXME: We should be warning about a use-after-free here, but we
+// temporarily "escape" retain counted objects stored to structs very eagerly
+// until we can properly tell whether they have escaped via a return value
+// or not.
CFAbsoluteTime f4() {
struct foo x;
@@ -110,7 +114,8 @@ CFAbsoluteTime f4() {
CFDateGetAbsoluteTime(date); // no-warning
x.f = (NSDate*) date;
[((NSDate*) date) release];
- t = CFDateGetAbsoluteTime(date); // expected-warning{{Reference-counted object is used after it is released}}
+ // FIXME: the following line should warn.
+ t = CFDateGetAbsoluteTime(date); // no-warning
return t;
}
diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m
index 8b0e7b83a7..fb02427eb4 100644
--- a/test/Analysis/retain-release.m
+++ b/test/Analysis/retain-release.m
@@ -1668,6 +1668,29 @@ void rdar_10824732() {
}
//===----------------------------------------------------------------------===//
+// Test returning allocated memory in a struct.
+//
+// We currently don't have a general way to track pointers that "escape".
+// Here we test that RetainCountChecker doesn't get excited about returning
+// allocated CF objects in struct fields.
+//===----------------------------------------------------------------------===//
+void *malloc(size_t);
+struct rdar11104566 { CFStringRef myStr; };
+struct rdar11104566 test_rdar11104566() {
+ CFStringRef cf = CFStringCreateWithCString( ((CFAllocatorRef)0), "test", kCFStringEncodingUTF8 ); // no-warning
+ struct rdar11104566 V;
+ V.myStr = cf;
+ return V; // no-warning
+}
+
+struct rdar11104566 *test_2_rdar11104566() {
+ CFStringRef cf = CFStringCreateWithCString( ((CFAllocatorRef)0), "test", kCFStringEncodingUTF8 ); // no-warning
+ struct rdar11104566 *V = (struct rdar11104566 *) malloc(sizeof(*V));
+ V->myStr = cf;
+ return V; // no-warning
+}
+
+//===----------------------------------------------------------------------===//
// ObjC literals support.
//===----------------------------------------------------------------------===//