[clang] [analyzer] Fix false positive for stack-addr leak on simple param ptr (PR #107003)
Arseniy Zaostrovnykh via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 2 19:21:12 PDT 2024
https://github.com/necto updated https://github.com/llvm/llvm-project/pull/107003
>From da5671efccd0ba56a0dd983b04d1f798c5c35d0d Mon Sep 17 00:00:00 2001
From: Arseniy Zaostrovnykh <necto.ne at gmail.com>
Date: Mon, 2 Sep 2024 17:13:14 +0200
Subject: [PATCH 1/2] [analyzer] Fix false positive for stack-addr leak on
simple param ptr
Assigning to a pointer parameter does not leak the stack address because
it stays within the function and is not shared with the caller.
Previous implementation reported any association of a pointer parameter
with a local address, which is too broad.
This fix enforces that the pointer to a stack variable is related by at
least one level of indirection.
CPP-5642
Fixes #106834
---
.../Checkers/StackAddrEscapeChecker.cpp | 2 ++
clang/test/Analysis/stack-addr-ps.cpp | 27 +++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
index ec577c36188e6c..5394c2257514dc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -420,6 +420,8 @@ void StackAddrEscapeChecker::checkEndFunction(const ReturnStmt *RS,
return true;
}
if (isa<StackArgumentsSpaceRegion>(ReferrerMemSpace) &&
+ // Not a simple ptr (int*) but something deeper, e.g. int**
+ isa<SymbolicRegion>(Referrer->getBaseRegion()) &&
ReferrerStackSpace->getStackFrame() == PoppedFrame && TopFrame) {
// Output parameter of a top-level function
V.emplace_back(Referrer, Referred);
diff --git a/clang/test/Analysis/stack-addr-ps.cpp b/clang/test/Analysis/stack-addr-ps.cpp
index 88bf6512165201..3c922dfb0ed454 100644
--- a/clang/test/Analysis/stack-addr-ps.cpp
+++ b/clang/test/Analysis/stack-addr-ps.cpp
@@ -791,3 +791,30 @@ void global_ptr_to_ptr() {
*global_pp = nullptr;
}
} // namespace leaking_via_indirect_global_invalidated
+
+namespace not_leaking_via_simple_ptr {
+void top(const char *p) {
+ char tmp;
+ p = &tmp;
+}
+
+extern void copy(char *output, const char *input, unsigned size);
+extern bool foo(const char *input);
+extern void bar(char *output, unsigned count);
+extern bool baz(char *output, const char *input);
+
+void repo(const char *input, char *output) {
+ char temp[64];
+ copy(temp, input, sizeof(temp));
+
+ char result[64];
+ input = temp;
+ if (foo(temp)) {
+ bar(result, sizeof(result));
+ input = result;
+ }
+ if (!baz(output, input)) {
+ copy(output, input, sizeof(result));
+ }
+}
+} // namespace not_leaking_via_simple_ptr
>From 8a9a76a3d1b19d8d2434e8c6de7fe41fe8cd8756 Mon Sep 17 00:00:00 2001
From: Arseniy Zaostrovnykh <necto.ne at gmail.com>
Date: Tue, 3 Sep 2024 04:20:56 +0200
Subject: [PATCH 2/2] Add tests
---
clang/test/Analysis/stack-addr-ps.cpp | 36 ++++++++++++++++++++++++---
1 file changed, 32 insertions(+), 4 deletions(-)
diff --git a/clang/test/Analysis/stack-addr-ps.cpp b/clang/test/Analysis/stack-addr-ps.cpp
index 3c922dfb0ed454..35f38fbbfbefdc 100644
--- a/clang/test/Analysis/stack-addr-ps.cpp
+++ b/clang/test/Analysis/stack-addr-ps.cpp
@@ -137,7 +137,7 @@ namespace rdar13296133 {
ConvertsToPointer obj;
return obj; // no-warning
}
-}
+} // namespace rdar13296133
void write_stack_address_to(char **q) {
char local;
@@ -793,9 +793,28 @@ void global_ptr_to_ptr() {
} // namespace leaking_via_indirect_global_invalidated
namespace not_leaking_via_simple_ptr {
-void top(const char *p) {
- char tmp;
- p = &tmp;
+void simple_ptr(const char *p) {
+ char tmp;
+ p = &tmp; // no-warning
+}
+
+void ref_ptr(const char *&p) {
+ char tmp;
+ p = &tmp; // expected-warning{{variable 'tmp' is still referred to by the caller variable 'p'}}
+}
+
+struct S {
+ const char *p;
+};
+
+void struct_ptr(S s) {
+ char tmp;
+ s.p = &tmp; // no-warning
+}
+
+void array(const char arr[2]) {
+ char tmp;
+ arr = &tmp; // no-warning
}
extern void copy(char *output, const char *input, unsigned size);
@@ -818,3 +837,12 @@ void repo(const char *input, char *output) {
}
}
} // namespace not_leaking_via_simple_ptr
+
+namespace early_reclaim_dead_limitation {
+void foo();
+void top(char **p) {
+ char local;
+ *p = &local;
+ foo(); // no-warning FIXME: p binding is reclaimed before the function end
+}
+} // namespace early_reclaim_dead_limitation
More information about the cfe-commits
mailing list