summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2019-04-26 02:05:15 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2019-04-26 02:05:15 +0000
commite264ac6ae19a5dfce26582c7240df402cba269ad (patch)
treece25df0b6952608932ca2d13301b1eb59196ce64
parentb591845f4b482a2aec74f121f5f03da2ebefcef4 (diff)
downloadbcm5719-llvm-e264ac6ae19a5dfce26582c7240df402cba269ad.tar.gz
bcm5719-llvm-e264ac6ae19a5dfce26582c7240df402cba269ad.zip
[analyzer] RetainCount: Allow offsets in return values.
Because RetainCountChecker has custom "local" reasoning about escapes, it has a separate facility to deal with tracked symbols at end of analysis and check them for leaks regardless of whether they're dead or not. This facility iterates over the list of tracked symbols and reports them as leaks, but it needs to treat the return value specially. Some custom allocators tend to return the value with an offset, storing extra metadata at the beginning of the buffer. In this case the return value would be a non-base region. In order to avoid false positives, we still need to find the original symbol within the return value, otherwise it'll be unable to match it to the item in the list of tracked symbols. Differential Revision: https://reviews.llvm.org/D60991 llvm-svn: 359263
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp6
-rw-r--r--clang/test/Analysis/retain-release.mm32
2 files changed, 36 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index cdda327d625..1ccf3829537 100644
--- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -970,8 +970,10 @@ ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
return Pred;
ProgramStateRef state = C.getState();
- SymbolRef Sym =
- state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol();
+ // We need to dig down to the symbolic base here because various
+ // custom allocators do sometimes return the symbol with an offset.
+ SymbolRef Sym = state->getSValAsScalarOrLoc(RetE, C.getLocationContext())
+ .getAsLocSymbol(/*IncludeBaseRegions=*/true);
if (!Sym)
return Pred;
diff --git a/clang/test/Analysis/retain-release.mm b/clang/test/Analysis/retain-release.mm
index ba864f817c5..1c0c1999d7f 100644
--- a/clang/test/Analysis/retain-release.mm
+++ b/clang/test/Analysis/retain-release.mm
@@ -515,3 +515,35 @@ void foo() {
}
}
+
+namespace reinterpret_casts {
+
+void *foo() {
+ void *p = const_cast<void *>(
+ reinterpret_cast<const void *>(CFArrayCreate(0, 0, 0, 0)));
+ void *q = reinterpret_cast<void *>(
+ reinterpret_cast<char *>(p) + 1);
+ // FIXME: Should warn about a leak here. The function should return at +0,
+ // but it returns at +1 instead.
+ return q;
+}
+
+void *fooCreate() {
+ void *p = const_cast<void *>(
+ reinterpret_cast<const void *>(CFArrayCreate(0, 0, 0, 0)));
+ void *q = reinterpret_cast<void *>(
+ reinterpret_cast<char *>(p) + 1);
+ // The function follows the Create Rule.
+ return q; // no-warning
+}
+
+void *fooBar() CF_RETURNS_RETAINED {
+ void *p = const_cast<void *>(
+ reinterpret_cast<const void *>(CFArrayCreate(0, 0, 0, 0)));
+ void *q = reinterpret_cast<void *>(
+ reinterpret_cast<char *>(p) + 1);
+ // The function follows the Create Rule.
+ return q; // no-warning
+}
+
+}
OpenPOWER on IntegriCloud