diff options
author | Ted Kremenek <kremenek@apple.com> | 2012-03-03 01:22:03 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2012-03-03 01:22:03 +0000 |
commit | 7e8678314cf19f28cfddb2d9d0567d993073ec7e (patch) | |
tree | 9b612b8ae0ab172742c3d23db014a5f95af0081c | |
parent | 1f73ae227b18073a5d1792b41094e61329179acf (diff) |
[analyzer] do not warn about returning stack-allocated memory when it comes from an ancestor stack frame.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151964 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp | 28 | ||||
-rw-r--r-- | test/Analysis/inline.c | 19 |
2 files changed, 37 insertions, 10 deletions
diff --git a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index d071ef8c1f..8c76cc523d 100644 --- a/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -113,7 +113,7 @@ void StackAddrEscapeChecker::EmitStackError(CheckerContext &C, const MemRegion * } void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS, - CheckerContext &C) const { + CheckerContext &C) const { const Expr *RetE = RS->getRetValue(); if (!RetE) @@ -122,18 +122,26 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS, SVal V = C.getState()->getSVal(RetE, C.getLocationContext()); const MemRegion *R = V.getAsRegion(); - if (!R || !R->hasStackStorage()) - return; + if (!R) + return; - if (R->hasStackStorage()) { - // Automatic reference counting automatically copies blocks. - if (C.getASTContext().getLangOptions().ObjCAutoRefCount && - isa<BlockDataRegion>(R)) - return; + const StackSpaceRegion *SS = + dyn_cast_or_null<StackSpaceRegion>(R->getMemorySpace()); + + if (!SS) + return; - EmitStackError(C, R, RetE); + // Return stack memory in an ancestor stack frame is fine. + const StackFrameContext *SFC = SS->getStackFrame(); + if (SFC != C.getLocationContext()->getCurrentStackFrame()) return; - } + + // Automatic reference counting automatically copies blocks. + if (C.getASTContext().getLangOptions().ObjCAutoRefCount && + isa<BlockDataRegion>(R)) + return; + + EmitStackError(C, R, RetE); } void StackAddrEscapeChecker::checkEndPath(CheckerContext &Ctx) const { diff --git a/test/Analysis/inline.c b/test/Analysis/inline.c index de807fb3aa..9e64d33690 100644 --- a/test/Analysis/inline.c +++ b/test/Analysis/inline.c @@ -58,3 +58,22 @@ void test_factorial_2() { *p = 0xDEADBEEF; // no-warning } } + +// Test that returning stack memory from a parent stack frame does +// not trigger a warning. +static char *return_buf(char *buf) { + return buf + 10; +} + +void test_return_stack_memory_ok() { + char stack_buf[100]; + char *pos = return_buf(stack_buf); + (void) pos; +} + +char *test_return_stack_memory_bad() { + char stack_buf[100]; + char *x = stack_buf; + return x; // expected-warning {{stack memory associated}} +} + |