Skip to content

Commit 48498ec

Browse files
committed
[-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)
1 parent 0cc2cd7 commit 48498ec

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,13 +560,22 @@ static bool hasUnsafeFormatOrSArg(const CallExpr *Call, const Expr *&UnsafeArg,
560560
const Expr *Fmt = Call->getArg(FmtArgIdx);
561561

562562
if (auto *SL = dyn_cast<StringLiteral>(Fmt->IgnoreParenImpCasts())) {
563-
StringRef FmtStr = SL->getString();
563+
StringRef FmtStr;
564+
565+
if (SL->getCharByteWidth() == 1)
566+
FmtStr = SL->getString();
567+
else if (auto EvaledFmtStr = SL->tryEvaluateString(Ctx))
568+
FmtStr = *EvaledFmtStr;
569+
else
570+
goto CHECK_UNSAFE_PTR;
571+
564572
StringFormatStringHandler Handler(Call, FmtArgIdx, UnsafeArg);
565573

566574
return analyze_format_string::ParsePrintfString(
567575
Handler, FmtStr.begin(), FmtStr.end(), Ctx.getLangOpts(),
568576
Ctx.getTargetInfo(), isKprintf);
569577
}
578+
CHECK_UNSAFE_PTR:
570579
// If format is not a string literal, we cannot analyze the format string.
571580
// In this case, this call is considered unsafe if at least one argument
572581
// (including the format argument) is unsafe pointer.

clang/test/SemaCXX/warn-unsafe-buffer-usage-libc-functions.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ int snwprintf_s( char* buffer, unsigned buf_size, const char* format, ... );
2020
int vsnprintf( char* buffer, unsigned buf_size, const char* format, ... );
2121
int sscanf_s(const char * buffer, const char * format, ...);
2222
int sscanf(const char * buffer, const char * format, ... );
23+
int wprintf(const wchar_t* format, ... );
2324
int __asan_printf();
2425

2526
namespace std {
@@ -83,9 +84,11 @@ void f(char * p, char * q, std::span<char> s, std::span<char> s2) {
8384
sscanf(p, "%s%d", "hello", *p); // expected-warning{{function 'sscanf' is unsafe}}
8485
sscanf_s(p, "%s%d", "hello", *p); // expected-warning{{function 'sscanf_s' is unsafe}}
8586
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}}
87+
wprintf(L"hello %s", p); // expected-warning{{function 'wprintf' is unsafe}} expected-note{{string argument is not guaranteed to be null-terminated}}
8688

8789
char a[10], b[11];
8890
int c[10];
91+
std::wstring WS;
8992

9093
snprintf(a, sizeof(b), "%s", __PRETTY_FUNCTION__); // expected-warning{{function 'snprintf' is unsafe}} expected-note{{buffer pointer and size may not match}}
9194
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) {
9598
snprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn
9699
snwprintf(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn
97100
snwprintf_s(s.data(), s.size_bytes(), "%s%d", __PRETTY_FUNCTION__, *p); // no warn
101+
wprintf(L"hello %ls", L"world"); // no warn
102+
wprintf(L"hello %ls", WS.c_str()); // no warn
98103
strlen("hello");// no warn
99104
__asan_printf();// a printf but no argument, so no warn
100105
}

0 commit comments

Comments
 (0)