[clang] [clang][analyzer] PutenvStackArrayChecker: No warning from 'main' (PR #93299)

Balázs Kéri via cfe-commits cfe-commits at lists.llvm.org
Fri May 24 06:25:53 PDT 2024


https://github.com/balazske created https://github.com/llvm/llvm-project/pull/93299

None

>From 9baa8cc3a1a738a43deee811b51593db85d5c88c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.keri at ericsson.com>
Date: Fri, 24 May 2024 15:22:22 +0200
Subject: [PATCH] [clang][analyzer] PutenvStackArrayChecker: No warning from
 'main'

---
 clang/docs/analyzer/checkers.rst              | 10 ++++++++++
 .../Checkers/PutenvStackArrayChecker.cpp      |  9 +++++++--
 clang/test/Analysis/putenv-stack-array.c      | 20 +++++++++++++++++++
 3 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/clang/docs/analyzer/checkers.rst b/clang/docs/analyzer/checkers.rst
index ac9f0b06f63ba..3a31708a1e9de 100644
--- a/clang/docs/analyzer/checkers.rst
+++ b/clang/docs/analyzer/checkers.rst
@@ -2858,6 +2858,16 @@ The check corresponds to CERT rule
     return putenv(env); // putenv function should not be called with stack-allocated string
   }
 
+There is one case where the checker can report a false positive. This is when
+the stack-allocated array is used at `putenv` in a function or code branch that
+does not return (calls `fork` or `exec` like function).
+
+Another special case is if the `putenv` is called from function `main`. Here
+the stack is deallocated at the end of the program and it should be no problem
+to use the stack-allocated string (a multi-threaded program may require more
+attention). The checker does not warn for cases when stack space of `main` is
+used at the `putenv` call.
+
 .. _alpha-security-ReturnPtrRange:
 
 alpha.security.ReturnPtrRange (C)
diff --git a/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp
index d59cebf0aa5cb..bf81d57bf82fd 100644
--- a/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/PutenvStackArrayChecker.cpp
@@ -44,9 +44,14 @@ void PutenvStackArrayChecker::checkPostCall(const CallEvent &Call,
 
   SVal ArgV = Call.getArgSVal(0);
   const Expr *ArgExpr = Call.getArgExpr(0);
-  const MemSpaceRegion *MSR = ArgV.getAsRegion()->getMemorySpace();
 
-  if (!isa<StackSpaceRegion>(MSR))
+  const auto *SSR =
+      dyn_cast<StackSpaceRegion>(ArgV.getAsRegion()->getMemorySpace());
+  if (!SSR)
+    return;
+  const auto *StackFrameFuncD =
+      dyn_cast_or_null<FunctionDecl>(SSR->getStackFrame()->getDecl());
+  if (StackFrameFuncD && StackFrameFuncD->isMain())
     return;
 
   StringRef ErrorMsg = "The 'putenv' function should not be called with "
diff --git a/clang/test/Analysis/putenv-stack-array.c b/clang/test/Analysis/putenv-stack-array.c
index fbbf93259ab85..f28aed73031d3 100644
--- a/clang/test/Analysis/putenv-stack-array.c
+++ b/clang/test/Analysis/putenv-stack-array.c
@@ -45,6 +45,15 @@ int test_auto_var_subarray() {
   return putenv(env + 100); // expected-warning{{The 'putenv' function should not be called with}}
 }
 
+int f_test_auto_var_call(char *env) {
+  return putenv(env); // expected-warning{{The 'putenv' function should not be called with}}
+}
+
+int test_auto_var_call() {
+  char env[1024];
+  return f_test_auto_var_call(env);
+}
+
 int test_constant() {
   char *env = "TEST";
   return putenv(env); // no-warning: data is not on the stack
@@ -68,3 +77,14 @@ void test_auto_var_reset() {
   // become invalid.
   putenv((char *)"NAME=anothervalue");
 }
+
+void f_main(char *env) {
+  putenv(env); // no warning: string allocated in stack of 'main'
+}
+
+int main(int argc, char **argv) {
+  char env[] = "NAME=value";
+  putenv(env); // no warning: string allocated in stack of 'main'
+  f_main(env);
+  return 0;
+}



More information about the cfe-commits mailing list