[clang] a49cf6c - [analyzer] Fix "sprintf" parameter modeling in CStringChecker

Balazs Benics via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 28 07:08:04 PST 2023


Author: Balazs Benics
Date: 2023-12-28T16:06:21+01:00
New Revision: a49cf6c14ad498244fee6026da59cfdcdad6b80c

URL: https://github.com/llvm/llvm-project/commit/a49cf6c14ad498244fee6026da59cfdcdad6b80c
DIFF: https://github.com/llvm/llvm-project/commit/a49cf6c14ad498244fee6026da59cfdcdad6b80c.diff

LOG: [analyzer] Fix "sprintf" parameter modeling in CStringChecker

`CE->getCalleeDecl()` returns `VarDecl` if the callee is actually a
function pointer variable. Consequently, calling `getAsFunction()` will
return null.

To workaround the case, we should use the `CallEvent::parameters()`,
which will internally recover the function being called and do the right
thing.

Fixes #74269
Depends on "[analyzer][NFC] Prefer CallEvent over CallExpr in APIs"

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
    clang/test/Analysis/string.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d3f352c6aabe79..e21ec78a1e8a77 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1115,6 +1115,9 @@ Crash and bug fixes
   `#59493 <https://github.com/llvm/llvm-project/issues/59493>`_,
   `#54533 <https://github.com/llvm/llvm-project/issues/54533>`_)
 
+- Fixed an ``alpha.unix.cstring`` crash on variadic functions.
+  (`#74269 <https://github.com/llvm/llvm-project/issues/74269>`_)
+
 - Fix false positive in mutation check when using pointer to member function.
   (`#66204 <https://github.com/llvm/llvm-project/issues/66204>`_)
 

diff  --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
index f5dbf9d82beeee..b7b64c3da4f6c8 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -2487,8 +2487,7 @@ void CStringChecker::evalSprintfCommon(CheckerContext &C, const CallEvent &Call,
   const auto *CE = cast<CallExpr>(Call.getOriginExpr());
   DestinationArgExpr Dest = {{Call.getArgExpr(0), 0}};
 
-  // FIXME: We should use `Call.parameters().size()` here.
-  const auto NumParams = CE->getCalleeDecl()->getAsFunction()->getNumParams();
+  const auto NumParams = Call.parameters().size();
   assert(CE->getNumArgs() >= NumParams);
 
   const auto AllArguments =

diff  --git a/clang/test/Analysis/string.cpp b/clang/test/Analysis/string.cpp
index f86416da6ee237..1be6c21466cc03 100644
--- a/clang/test/Analysis/string.cpp
+++ b/clang/test/Analysis/string.cpp
@@ -1,6 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix -verify %s
-
-// expected-no-diagnostics
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix,debug.ExprInspection -verify %s
 
 // Test functions that are called "memcpy" but aren't the memcpy
 // we're looking for. Unfortunately, this test cannot be put into
@@ -9,6 +7,11 @@
 typedef __typeof(sizeof(int)) size_t;
 void *memcpy(void *, const void *, size_t);
 
+int sprintf(char *str, const char *format, ...);
+int snprintf(char *str, size_t size, const char *format, ...);
+
+void clang_analyzer_warnIfReached();
+
 struct S {
   static S s1, s2;
 
@@ -26,3 +29,19 @@ void *memcpy(void *, const S &, size_t);
 void test_out_of_class_weird_memcpy() {
   memcpy(&S::s1, S::s2, 1); // no-crash
 }
+
+template<typename... Args>
+void log(const char* fmt, const Args&... args) {
+  char buf[100] = {};
+  auto f = snprintf;
+  auto g = sprintf;
+  int n = 0;
+  n += f(buf, 99, fmt, args...); // no-crash: The CalleeDecl is a VarDecl, but it's okay.
+  n += g(buf, fmt, args...); // no-crash: Same.
+  (void)n;
+  clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
+}
+
+void test_gh_74269_no_crash() {
+  log("%d", 1);
+}


        


More information about the cfe-commits mailing list