[clang] 48498ec - [-Wunsafe-buffer-usage] Fix a bug in "Re-land [-Wunsafe-buffer-usage] Warning Libc functions (#101583)"

via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 16 17:24:44 PDT 2024


Author: ziqingluo-90
Date: 2024-09-16T17:21:24-07:00
New Revision: 48498ec7a4ded9f1bf813051abdc54c3e5b66fa7

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

LOG: [-Wunsafe-buffer-usage] Fix a bug in "Re-land [-Wunsafe-buffer-usage] Warning Libc functions (#101583)"

StringLiteral::getString() is not applicable to strings of wide
characters.  Added handling for that.

(rdar://117182250)

Added: 
    

Modified: 
    clang/lib/Analysis/UnsafeBufferUsage.cpp
    clang/test/SemaCXX/warn-unsafe-buffer-usage-libc-functions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index a00b166a8b4f93..a16762244b1766 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -560,13 +560,22 @@ static bool hasUnsafeFormatOrSArg(const CallExpr *Call, const Expr *&UnsafeArg,
   const Expr *Fmt = Call->getArg(FmtArgIdx);
 
   if (auto *SL = dyn_cast<StringLiteral>(Fmt->IgnoreParenImpCasts())) {
-    StringRef FmtStr = SL->getString();
+    StringRef FmtStr;
+
+    if (SL->getCharByteWidth() == 1)
+      FmtStr = SL->getString();
+    else if (auto EvaledFmtStr = SL->tryEvaluateString(Ctx))
+      FmtStr = *EvaledFmtStr;
+    else
+      goto CHECK_UNSAFE_PTR;
+
     StringFormatStringHandler Handler(Call, FmtArgIdx, UnsafeArg);
 
     return analyze_format_string::ParsePrintfString(
         Handler, FmtStr.begin(), FmtStr.end(), Ctx.getLangOpts(),
         Ctx.getTargetInfo(), isKprintf);
   }
+CHECK_UNSAFE_PTR:
   // If format is not a string literal, we cannot analyze the format string.
   // In this case, this call is considered unsafe if at least one argument
   // (including the format argument) is unsafe pointer.

diff  --git a/clang/test/SemaCXX/warn-unsafe-buffer-usage-libc-functions.cpp b/clang/test/SemaCXX/warn-unsafe-buffer-usage-libc-functions.cpp
index 8e777a7a51c994..25b6d8e9e22dc2 100644
--- a/clang/test/SemaCXX/warn-unsafe-buffer-usage-libc-functions.cpp
+++ b/clang/test/SemaCXX/warn-unsafe-buffer-usage-libc-functions.cpp
@@ -20,6 +20,7 @@ int snwprintf_s( char* buffer, unsigned buf_size, const char* format, ... );
 int vsnprintf( char* buffer, unsigned buf_size, const char* format, ... );
 int sscanf_s(const char * buffer, const char * format, ...);
 int sscanf(const char * buffer, const char * format, ... );
+int wprintf(const wchar_t* format, ... );
 int __asan_printf();
 
 namespace std {
@@ -83,9 +84,11 @@ void f(char * p, char * q, std::span<char> s, std::span<char> s2) {
   sscanf(p, "%s%d", "hello", *p);    // expected-warning{{function 'sscanf' is unsafe}}
   sscanf_s(p, "%s%d", "hello", *p);  // expected-warning{{function 'sscanf_s' is unsafe}}
   fprintf((FILE*)p, "%P%d%p%i hello world %32s", *p, *p, p, *p, p); // expected-warning{{function 'fprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}
+  wprintf(L"hello %s", p); // expected-warning{{function 'wprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}
 
   char a[10], b[11];
   int c[10];
+  std::wstring WS;
 
   snprintf(a, sizeof(b), "%s", __PRETTY_FUNCTION__);         // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}
   snprintf((char*)c, sizeof(c), "%s", __PRETTY_FUNCTION__);  // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}
@@ -95,6 +98,8 @@ void f(char * p, char * q, std::span<char> s, std::span<char> s2) {
   snprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn
   snwprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn
   snwprintf_s(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn
+  wprintf(L"hello %ls", L"world"); // no warn
+  wprintf(L"hello %ls", WS.c_str()); // no warn
   strlen("hello");// no warn
   __asan_printf();// a printf but no argument, so no warn
 }


        


More information about the cfe-commits mailing list