Skip to content

Commit

Permalink
[-Wunsafe-buffer-usage] Fix a bug in "Re-land [-Wunsafe-buffer-usage]…
Browse files Browse the repository at this point in the history
… Warning Libc functions (llvm#101583)"

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

(rdar://117182250)
  • Loading branch information
ziqingluo-90 committed Sep 17, 2024
1 parent 0cc2cd7 commit 48498ec
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 1 deletion.
11 changes: 10 additions & 1 deletion clang/lib/Analysis/UnsafeBufferUsage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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}}
Expand All @@ -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
}
Expand Down

0 comments on commit 48498ec

Please sign in to comment.