From: Ted Kremenek Date: Sat, 3 Mar 2012 01:22:03 +0000 (+0000) Subject: [analyzer] do not warn about returning stack-allocated memory when it comes from... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7e8678314cf19f28cfddb2d9d0567d993073ec7e;p=clang [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 --- 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(R)) - return; + const StackSpaceRegion *SS = + dyn_cast_or_null(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(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}} +} +