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

Reply via email to