[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