diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index d8c52941b19366..a76639bb86b208 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -337,6 +337,10 @@ static std::optional printReferrer(const MemRegion *Referrer) { // warn_bind_ref_member_to_parameter or // warn_init_ptr_member_to_parameter_addr return std::nullopt; + } else if (isa(Referrer)) { + // Skip alloca() regions, they indicate advanced memory management + // and higher likelihood of CSA false positives. + return std::nullopt; } else { assert(false && "Unexpected referrer region type."); return std::nullopt; diff --git a/clang/test/Analysis/stack-addr-ps.cpp b/clang/test/Analysis/stack-addr-ps.cpp index 35f38fbbfbefdc..73e9dbeca460f6 100644 --- a/clang/test/Analysis/stack-addr-ps.cpp +++ b/clang/test/Analysis/stack-addr-ps.cpp @@ -1,10 +1,23 @@ -// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s -Wno-undefined-bool-conversion +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=core,debug.ExprInspection \ +// RUN: -verify %s \ +// RUN: -Wno-undefined-bool-conversion +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=core,debug.ExprInspection,unix.Malloc \ +// RUN: -verify %s \ +// RUN: -Wno-undefined-bool-conversion +// unix.Malloc is necessary to model __builtin_alloca, +// which could trigger an "unexpected region" bug in StackAddrEscapeChecker. typedef __INTPTR_TYPE__ intptr_t; template void clang_analyzer_dump(T x); +using size_t = decltype(sizeof(int)); +void * malloc(size_t size); +void free(void*); + const int& g() { int s; return s; // expected-warning{{Address of stack memory associated with local variable 's' returned}} expected-warning{{reference to stack memory associated with local variable 's' returned}} @@ -846,3 +859,21 @@ void top(char **p) { foo(); // no-warning FIXME: p binding is reclaimed before the function end } } // namespace early_reclaim_dead_limitation + +namespace alloca_region_pointer { +void callee(char **pptr) { + char local; + *pptr = &local; +} // no crash + +void top_alloca_no_crash_fn() { + char **pptr = (char**)__builtin_alloca(sizeof(char*)); + callee(pptr); +} + +void top_malloc_no_crash_fn() { + char **pptr = (char**)malloc(sizeof(char*)); + callee(pptr); + free(pptr); +} +} // namespace alloca_region_pointer