https://github.com/venk-ks updated https://github.com/llvm/llvm-project/pull/220341
>From d87d02c17d1179addb302dfa931ea070b2b792a5 Mon Sep 17 00:00:00 2001 From: Venkatesh Srinivasan <[email protected]> Date: Tue, 1 Sep 2026 19:00:15 +0000 Subject: [PATCH] [Clang][Sema] Add fortify warnings for strlcat Add -Wfortify-source diagnostics for strlcat and __builtin_strlcat when the size argument exceeds the destination buffer size. Part of #142230 Assisted-by: Gemini --- clang/docs/ReleaseNotes.md | 3 +++ clang/include/clang/Basic/Builtins.td | 1 + clang/lib/AST/Decl.cpp | 3 +++ clang/lib/Sema/SemaChecking.cpp | 4 +++- clang/test/Sema/builtins.c | 3 ++- clang/test/Sema/warn-fortify-source.c | 6 ++++++ 6 files changed, 18 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 4f775d0125343..79a85e3ffb209 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -263,6 +263,9 @@ features cannot lower the translation-unit ABI level; ### Improvements to Clang's diagnostics +- `-Wfortify-source` now diagnoses when `strlcat` is called with a size + argument larger than the destination buffer. + - The `cannot overload a member function` diagnostic now describes the previous declaration first, matching the order in which the declarations appear in the source. (#GH219803) diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index 49fe879c6add1..4932f4037ac7e 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -3917,6 +3917,7 @@ def StrlCpy : GNULibBuiltin<"string.h"> { def StrlCat : GNULibBuiltin<"string.h"> { let Spellings = ["strlcat"]; let Prototype = "size_t(char*, char const*, size_t)"; + let AddBuiltinPrefixedAlias = 1; } def ObjcMsgSend : ObjCLibBuiltin<"objc_message.h"> { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 03eb04d53cdf4..a620e9f211ca6 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4644,6 +4644,7 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { case Builtin::BI__builtin___strlcpy_chk: return Builtin::BIstrlcpy; + case Builtin::BI__builtin_strlcat: case Builtin::BIstrlcat: case Builtin::BI__builtin___strlcat_chk: return Builtin::BIstrlcat; @@ -4723,6 +4724,8 @@ unsigned FunctionDecl::getMemoryFunctionKind() const { return Builtin::BIbzero; if (FnInfo->isStr("bcopy")) return Builtin::BIbcopy; + if (FnInfo->isStr("strlcat")) + return Builtin::BIstrlcat; } else if (isInStdNamespace()) { if (FnInfo->isStr("free")) return Builtin::BIfree; diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 7b4dca61f70dc..50fca0aa4b21f 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1450,7 +1450,9 @@ void Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD, case Builtin::BIstrncpy: case Builtin::BI__builtin_strncpy: case Builtin::BIstpncpy: - case Builtin::BI__builtin_stpncpy: { + case Builtin::BI__builtin_stpncpy: + case Builtin::BIstrlcat: + case Builtin::BI__builtin_strlcat: { // Whether these functions overflow depends on the runtime strlen of the // string, not just the buffer size, so emitting the "always overflow" // diagnostic isn't quite right. We should still diagnose passing a buffer diff --git a/clang/test/Sema/builtins.c b/clang/test/Sema/builtins.c index b669ee68cdd95..5a474909d37e9 100644 --- a/clang/test/Sema/builtins.c +++ b/clang/test/Sema/builtins.c @@ -229,7 +229,8 @@ void Test19(void) // expected-warning {{'strlcpy' will always overflow; destination buffer has size 20, but size argument is 40}} strlcat(buf, b, sizeof(b)); // expected-warning {{size argument in 'strlcat' call appears to be size of the source; expected the size of the destination}} \ - // expected-note {{change size argument to be the size of the destination}} + // expected-note {{change size argument to be the size of the destination}} \ + // expected-warning {{'strlcat' size argument is too large; destination buffer has size 20, but size argument is 40}} __builtin___strlcat_chk(buf, b, sizeof(b), __builtin_object_size(buf, 0)); // expected-warning {{size argument in '__builtin___strlcat_chk' call appears to be size of the source; expected the size of the destination}} \ // expected-note {{change size argument to be the size of the destination}} \ diff --git a/clang/test/Sema/warn-fortify-source.c b/clang/test/Sema/warn-fortify-source.c index 0a6c44f59af9e..77f7e0750e816 100644 --- a/clang/test/Sema/warn-fortify-source.c +++ b/clang/test/Sema/warn-fortify-source.c @@ -69,6 +69,12 @@ void call_stpncpy(void) { __builtin_stpncpy(s1, s2, 20); // expected-warning {{'stpncpy' size argument is too large; destination buffer has size 10, but size argument is 20}} } +void call_strlcat(void) { + char s1[10], s2[20]; + __builtin_strlcat(s2, s1, 20); + __builtin_strlcat(s1, s2, 20); // expected-warning {{'strlcat' size argument is too large; destination buffer has size 10, but size argument is 20}} +} + void call_strcpy(void) { const char *const src = "abcd"; char dst[4]; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
