https://github.com/ColinKinloch updated 
https://github.com/llvm/llvm-project/pull/161737

>From 98912f07d2b6f3a1d8c79d2e38407dc1d9ba2905 Mon Sep 17 00:00:00 2001
From: Colin Kinloch <[email protected]>
Date: Thu, 2 Oct 2025 22:01:40 +0100
Subject: [PATCH 1/7] [clang][Sema] Add fortify warnings for `unistd.h`

Define as builtin and check for overflows and over-reads in:
* `read`
* `pread`/`pread64`
* `write`
* `pwrite`/`pwrite64`
* `getcwd`
* `readlink`
* `readlinkat`

It also enables `off_t`, `off64_t` and `ssize_t` for use in builtin
signatures.

Signed-off-by: Colin Kinloch <[email protected]>
---
 clang/include/clang/Basic/Builtins.td         | 65 +++++++++++++++++
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 ++
 clang/lib/AST/ASTContext.cpp                  |  9 ++-
 clang/lib/Sema/SemaChecking.cpp               | 70 ++++++++++++++++++-
 clang/test/Sema/warn-fortify-source.c         | 55 +++++++++++++++
 clang/utils/TableGen/ClangBuiltinsEmitter.cpp |  3 +
 6 files changed, 201 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index 468121f7d20ab..3c3a5a82a28a6 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -3490,6 +3490,8 @@ def StrnCaseCmp : GNULibBuiltin<"strings.h"> {
   let RequiresUndef = 1;
 }
 
+// POSIX unistd.h
+
 def GNU_Exit : GNULibBuiltin<"unistd.h"> {
   let Spellings = ["_exit"];
   let Attributes = [NoReturn];
@@ -3502,6 +3504,69 @@ def VFork : LibBuiltin<"unistd.h"> {
   let Prototype = "pid_t()";
 }
 
+def Read : LibBuiltin<"unistd.h"> {
+  let Spellings = ["read"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(int, void*, size_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def PRead : LibBuiltin<"unistd.h"> {
+  let Spellings = ["pread"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(int, void*, size_t, off_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def PRead64 : LibBuiltin<"unistd.h"> {
+  let Spellings = ["pread64"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(int, void*, size_t, off64_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def Write : LibBuiltin<"unistd.h"> {
+  let Spellings = ["write"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(int, void const*, size_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def PWrite : LibBuiltin<"unistd.h"> {
+  let Spellings = ["pwrite"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(int, void const*, size_t, off_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def PWrite64 : LibBuiltin<"unistd.h"> {
+  let Spellings = ["pwrite64"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(int, void const*, size_t, off64_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def GetCWD : LibBuiltin<"unistd.h"> {
+  let Spellings = ["getcwd"];
+  let Attributes = [NoThrow];
+  let Prototype = "char*(char*, size_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def ReadLink : LibBuiltin<"unistd.h"> {
+  let Spellings = ["readlink"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(char const* restrict, char* restrict, size_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
+def ReadLinkAt : LibBuiltin<"unistd.h"> {
+  let Spellings = ["readlinkat"];
+  let Attributes = [NoThrow];
+  let Prototype = "ssize_t(int, char const* restrict, char* restrict, size_t)";
+  let AddBuiltinPrefixedAlias = 1;
+}
+
 // POSIX pthread.h
 
 def PthreadCreate : GNULibBuiltin<"pthread.h"> {
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b157cbb0b8069..f2206ad08414e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -953,6 +953,10 @@ def warn_fortify_source_overflow
 def warn_fortify_source_size_mismatch : Warning<
   "'%0' size argument is too large; destination buffer has size %1,"
   " but size argument is %2">, InGroup<FortifySource>;
+def warn_fortify_destination_size_mismatch
+    : Warning<"'%0' size argument is too large; source buffer has size %2,"
+              " but size argument is %1">,
+      InGroup<FortifySource>;
 
 def warn_fortify_strlen_overflow: Warning<
   "'%0' will always overflow; destination buffer has size %1,"
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 056bfe36b2a0a..d0432de14dbb3 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -12528,9 +12528,12 @@ static QualType DecodeTypeFromStr(const char *&Str, 
const ASTContext &Context,
     assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'b'!");
     Type = Context.BoolTy;
     break;
-  case 'z':  // size_t.
-    assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'z'!");
-    Type = Context.getSizeType();
+  case 'z': // size_t and ssize_t.
+    assert(HowLong == 0 && "Bad modifiers for 'z'!");
+    if (Signed)
+      Type = Context.getSignedSizeType();
+    else
+      Type = Context.getSizeType();
     break;
   case 'w':  // wchar_t.
     assert(HowLong == 0 && !Signed && !Unsigned && "Bad modifiers for 'w'!");
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 7b37e0b8d5430..c7d6d0c142eee 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1243,6 +1243,14 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   std::optional<llvm::APSInt> DestinationSize;
   unsigned DiagID = 0;
   bool IsChkVariant = false;
+  bool IsTriggered = false;
+
+  auto CompareSizeSourceToDest = [&]() {
+    return SourceSize && DestinationSize
+               ? std::optional<int>{llvm::APSInt::compareValues(
+                     *SourceSize, *DestinationSize)}
+               : std::nullopt;
+  };
 
   auto GetFunctionName = [&]() {
     std::string FunctionNameStr =
@@ -1270,6 +1278,7 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     DiagID = diag::warn_fortify_strlen_overflow;
     SourceSize = ComputeStrLenArgument(1);
     DestinationSize = ComputeSizeArgument(0);
+    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1279,6 +1288,7 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     SourceSize = ComputeStrLenArgument(1);
     DestinationSize = ComputeExplicitObjectSizeArgument(2);
     IsChkVariant = true;
+    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1349,11 +1359,13 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
         } else {
           DestinationSize = ComputeSizeArgument(0);
         }
+        IsTriggered = CompareSizeSourceToDest() > 0;
         break;
       }
     }
     return;
   }
+
   case Builtin::BI__builtin___memcpy_chk:
   case Builtin::BI__builtin___memmove_chk:
   case Builtin::BI__builtin___memset_chk:
@@ -1369,6 +1381,7 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     DestinationSize =
         ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     IsChkVariant = true;
+    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1378,6 +1391,7 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     SourceSize = ComputeExplicitObjectSizeArgument(1);
     DestinationSize = ComputeExplicitObjectSizeArgument(3);
     IsChkVariant = true;
+    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1395,6 +1409,7 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     DiagID = diag::warn_fortify_source_size_mismatch;
     SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     DestinationSize = ComputeSizeArgument(0);
+    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1409,8 +1424,58 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     DiagID = diag::warn_fortify_source_overflow;
     SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     DestinationSize = ComputeSizeArgument(0);
+    IsTriggered = CompareSizeSourceToDest() > 0;
+    break;
+  }
+
+  case Builtin::BIread:
+  case Builtin::BI__builtin_read:
+  case Builtin::BIreadlink:
+  case Builtin::BI__builtin_readlink:
+  case Builtin::BIreadlinkat:
+  case Builtin::BI__builtin_readlinkat:
+  case Builtin::BIgetcwd:
+  case Builtin::BI__builtin_getcwd: {
+    DiagID = diag::warn_fortify_source_size_mismatch;
+    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
+    DestinationSize = ComputeSizeArgument(TheCall->getNumArgs() - 2);
+    IsTriggered = CompareSizeSourceToDest() > 0;
+    break;
+  }
+
+  case Builtin::BIpread:
+  case Builtin::BI__builtin_pread:
+  case Builtin::BIpread64:
+  case Builtin::BI__builtin_pread64: {
+    DiagID = diag::warn_fortify_source_size_mismatch;
+    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
+    DestinationSize = ComputeSizeArgument(TheCall->getNumArgs() - 3);
+    IsTriggered = CompareSizeSourceToDest() > 0;
+    break;
+  }
+
+  case Builtin::BIwrite:
+  case Builtin::BI__builtin_write: {
+    DiagID = diag::warn_fortify_destination_size_mismatch;
+    SourceSize = ComputeSizeArgument(TheCall->getNumArgs() - 2);
+    DestinationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
+    IsTriggered = CompareSizeSourceToDest() < 0;
     break;
   }
+
+  case Builtin::BIpwrite:
+  case Builtin::BI__builtin_pwrite:
+  case Builtin::BIpwrite64:
+  case Builtin::BI__builtin_pwrite64: {
+    DiagID = diag::warn_fortify_destination_size_mismatch;
+    SourceSize = ComputeSizeArgument(TheCall->getNumArgs() - 3);
+    DestinationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
+    IsTriggered = CompareSizeSourceToDest() < 0;
+    break;
+  }
+
   case Builtin::BIsnprintf:
   case Builtin::BI__builtin_snprintf:
   case Builtin::BIvsnprintf:
@@ -1446,11 +1511,12 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
       }
     }
     DestinationSize = ComputeSizeArgument(0);
+    IsTriggered = CompareSizeSourceToDest() > 0;
+    break;
   }
   }
 
-  if (!SourceSize || !DestinationSize ||
-      llvm::APSInt::compareValues(*SourceSize, *DestinationSize) <= 0)
+  if (!IsTriggered)
     return;
 
   std::string FunctionName = GetFunctionName();
diff --git a/clang/test/Sema/warn-fortify-source.c 
b/clang/test/Sema/warn-fortify-source.c
index 216878c0836d8..5d4a8d81b0b3e 100644
--- a/clang/test/Sema/warn-fortify-source.c
+++ b/clang/test/Sema/warn-fortify-source.c
@@ -96,6 +96,61 @@ void call_memset(void) {
   __builtin_memset(buf, 0xff, 11); // expected-warning {{'memset' will always 
overflow; destination buffer has size 10, but size argument is 11}}
 }
 
+void call_read(void) {
+  char buf[10];
+  __builtin_read(0, buf, 10);
+  __builtin_read(0, buf, 20); // expected-warning {{'read' size argument is 
too large; destination buffer has size 10, but size argument is 20}}
+}
+
+void call_pread(void) {
+  char buf[10];
+  __builtin_pread(0, buf, 10, 0);
+  __builtin_pread(0, buf, 20, 0); // expected-warning {{'pread' size argument 
is too large; destination buffer has size 10, but size argument is 20}}
+}
+
+void call_pread64(void) {
+  char buf[10];
+  __builtin_pread64(0, buf, 10, 0);
+  __builtin_pread64(0, buf, 20, 0); // expected-warning {{'pread64' size 
argument is too large; destination buffer has size 10, but size argument is 20}}
+}
+
+void call_write(void) {
+  char buf[10];
+  __builtin_write(0, buf, 10);
+  __builtin_write(0, buf, 20); // expected-warning {{'write' size argument is 
too large; source buffer has size 10, but size argument is 20}}
+}
+
+void call_pwrite(void) {
+  char buf[10];
+  __builtin_pwrite(0, buf, 10, 0);
+  __builtin_pwrite(0, buf, 20, 0); // expected-warning {{'pwrite' size 
argument is too large; source buffer has size 10, but size argument is 20}}
+}
+
+void call_pwrite64(void) {
+  char buf[10];
+  __builtin_pwrite64(0, buf, 10, 0);
+  __builtin_pwrite64(0, buf, 20, 0); // expected-warning {{'pwrite64' size 
argument is too large; source buffer has size 10, but size argument is 20}}
+}
+
+void call_getcwd(void) {
+  char buf[10];
+  __builtin_getcwd(buf, 10);
+  __builtin_getcwd(buf, 20); // expected-warning {{'getcwd' size argument is 
too large; destination buffer has size 10, but size argument is 20}}
+}
+
+void call_readlink(void) {
+  char buf[10];
+  __builtin_readlink("path", buf, 10);
+  __builtin_readlink("path", buf, 20); // expected-warning {{'readlink' size 
argument is too large; destination buffer has size 10, but size argument is 20}}
+}
+
+void call_readlinkat(void) {
+  char buf[10];
+  __builtin_readlinkat(0, "path", buf, 10);
+  __builtin_readlinkat(0, "path", buf, 20); // expected-warning {{'readlinkat' 
size argument is too large; destination buffer has size 10, but size argument 
is 20}}
+}
+
+
 void call_snprintf(double d, int n) {
   char buf[10];
   __builtin_snprintf(buf, 10, "merp");
diff --git a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp 
b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
index 352765acf5338..30c7afd95a89a 100644
--- a/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
+++ b/clang/utils/TableGen/ClangBuiltinsEmitter.cpp
@@ -347,12 +347,15 @@ class PrototypeParser {
                                .Case("msint32_t", "Ni")
                                .Case("msuint32_t", "UNi")
                                .Case("objc_super", "M")
+                               .Case("off_t", "Li")
+                               .Case("off64_t", "Wi")
                                .Case("pid_t", "p")
                                .Case("ptrdiff_t", "Y")
                                .Case("SEL", "H")
                                .Case("short", "s")
                                .Case("sigjmp_buf", "SJ")
                                .Case("size_t", "z")
+                               .Case("ssize_t", "Sz")
                                .Case("ucontext_t", "K")
                                .Case("uint32_t", "UZi")
                                .Case("uint64_t", "UWi")

>From 496eec840f8f0903da2b6cbd440631962ebad5e9 Mon Sep 17 00:00:00 2001
From: Colin Kinloch <[email protected]>
Date: Mon, 3 Nov 2025 02:53:09 +0000
Subject: [PATCH 2/7] [clang][Sema] Add min/max operation size for fortify
 checks

---
 .../clang/Basic/DiagnosticSemaKinds.td        |   8 +-
 clang/lib/Sema/SemaChecking.cpp               | 162 +++++++++++-------
 clang/test/Sema/builtin-memcpy.c              |   3 +-
 clang/test/Sema/warn-fortify-source.c         |  39 ++++-
 4 files changed, 140 insertions(+), 72 deletions(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f2206ad08414e..484f161194199 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -950,12 +950,16 @@ def warn_builtin_chk_overflow : Warning<
 
 def warn_fortify_source_overflow
   : Warning<warn_builtin_chk_overflow.Summary>, InGroup<FortifySource>;
+def warn_fortify_destination_over_read
+    : Warning<"'%0' will always over-read; source buffer has size %1,"
+              " but size argument is %2">,
+      InGroup<FortifySource>;
 def warn_fortify_source_size_mismatch : Warning<
   "'%0' size argument is too large; destination buffer has size %1,"
   " but size argument is %2">, InGroup<FortifySource>;
 def warn_fortify_destination_size_mismatch
-    : Warning<"'%0' size argument is too large; source buffer has size %2,"
-              " but size argument is %1">,
+    : Warning<"'%0' size argument is too large; source buffer has size %1,"
+              " but size argument is %2">,
       InGroup<FortifySource>;
 
 def warn_fortify_strlen_overflow: Warning<
diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index c7d6d0c142eee..3889a07d5f962 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1239,18 +1239,20 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     return llvm::APSInt::getUnsigned(Result + 1).extOrTrunc(SizeTypeWidth);
   };
 
+  // Size of the memory read from
   std::optional<llvm::APSInt> SourceSize;
+  // Size of the memory written to
   std::optional<llvm::APSInt> DestinationSize;
-  unsigned DiagID = 0;
+  // Maximum operation size for detecting possible out of bounds access
+  std::optional<llvm::APSInt> MaxOperationSize;
+  // Minimum operation size for detecting definate out of bounds access
+  std::optional<llvm::APSInt> MinOperationSize;
+
+  unsigned DiagOverflowID = diag::warn_fortify_source_overflow;
+  unsigned DiagMayOverflowID = diag::warn_fortify_source_size_mismatch;
+  unsigned DiagOverReadID = diag::warn_fortify_destination_over_read;
+  unsigned DiagMayOverReadID = diag::warn_fortify_destination_size_mismatch;
   bool IsChkVariant = false;
-  bool IsTriggered = false;
-
-  auto CompareSizeSourceToDest = [&]() {
-    return SourceSize && DestinationSize
-               ? std::optional<int>{llvm::APSInt::compareValues(
-                     *SourceSize, *DestinationSize)}
-               : std::nullopt;
-  };
 
   auto GetFunctionName = [&]() {
     std::string FunctionNameStr =
@@ -1275,20 +1277,18 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   case Builtin::BIstpcpy:
   case Builtin::BI__builtin_strcpy:
   case Builtin::BIstrcpy: {
-    DiagID = diag::warn_fortify_strlen_overflow;
-    SourceSize = ComputeStrLenArgument(1);
+    DiagOverflowID = diag::warn_fortify_strlen_overflow;
+    MinOperationSize = ComputeStrLenArgument(1);
     DestinationSize = ComputeSizeArgument(0);
-    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
   case Builtin::BI__builtin___stpcpy_chk:
   case Builtin::BI__builtin___strcpy_chk: {
-    DiagID = diag::warn_fortify_strlen_overflow;
-    SourceSize = ComputeStrLenArgument(1);
+    DiagOverflowID = diag::warn_fortify_strlen_overflow;
+    MinOperationSize = ComputeStrLenArgument(1);
     DestinationSize = ComputeExplicitObjectSizeArgument(2);
     IsChkVariant = true;
-    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1312,12 +1312,12 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
 
     auto Diagnose = [&](unsigned ArgIndex, unsigned DestSize,
                         unsigned SourceSize) {
-      DiagID = diag::warn_fortify_scanf_overflow;
       unsigned Index = ArgIndex + DataIndex;
       std::string FunctionName = GetFunctionName();
       DiagRuntimeBehavior(TheCall->getArg(Index)->getBeginLoc(), TheCall,
-                          PDiag(DiagID) << FunctionName << (Index + 1)
-                                        << DestSize << SourceSize);
+                          PDiag(diag::warn_fortify_scanf_overflow)
+                              << FunctionName << (Index + 1) << DestSize
+                              << SourceSize);
     };
 
     auto ShiftedComputeSizeArgument = [&](unsigned Index) {
@@ -1348,18 +1348,17 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
       if (!analyze_format_string::ParsePrintfString(
               H, FormatBytes, FormatBytes + StrLen, getLangOpts(),
               Context.getTargetInfo(), false)) {
-        DiagID = H.isKernelCompatible()
-                     ? diag::warn_format_overflow
-                     : diag::warn_format_overflow_non_kprintf;
-        SourceSize = llvm::APSInt::getUnsigned(H.getSizeLowerBound())
-                         .extOrTrunc(SizeTypeWidth);
+        DiagOverflowID = H.isKernelCompatible()
+                             ? diag::warn_format_overflow
+                             : diag::warn_format_overflow_non_kprintf;
+        MinOperationSize = llvm::APSInt::getUnsigned(H.getSizeLowerBound())
+                               .extOrTrunc(SizeTypeWidth);
         if (BuiltinID == Builtin::BI__builtin___sprintf_chk) {
           DestinationSize = ComputeExplicitObjectSizeArgument(2);
           IsChkVariant = true;
         } else {
           DestinationSize = ComputeSizeArgument(0);
         }
-        IsTriggered = CompareSizeSourceToDest() > 0;
         break;
       }
     }
@@ -1376,22 +1375,21 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   case Builtin::BI__builtin___stpncpy_chk:
   case Builtin::BI__builtin___memccpy_chk:
   case Builtin::BI__builtin___mempcpy_chk: {
-    DiagID = diag::warn_builtin_chk_overflow;
-    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
+    DiagOverflowID = diag::warn_builtin_chk_overflow;
+    MinOperationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
     DestinationSize =
         ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     IsChkVariant = true;
-    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
   case Builtin::BI__builtin___snprintf_chk:
   case Builtin::BI__builtin___vsnprintf_chk: {
-    DiagID = diag::warn_builtin_chk_overflow;
-    SourceSize = ComputeExplicitObjectSizeArgument(1);
+    DiagOverflowID = diag::warn_builtin_chk_overflow;
+    MinOperationSize = ComputeExplicitObjectSizeArgument(1);
     DestinationSize = ComputeExplicitObjectSizeArgument(3);
     IsChkVariant = true;
-    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1406,10 +1404,17 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
     // diagnostic isn't quite right. We should still diagnose passing a buffer
     // size larger than the destination buffer though; this is a runtime abort
     // in _FORTIFY_SOURCE mode, and is quite suspicious otherwise.
-    DiagID = diag::warn_fortify_source_size_mismatch;
-    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
+    MaxOperationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
+    DestinationSize = ComputeSizeArgument(0);
+    break;
+  }
+
+  case Builtin::BImemset:
+  case Builtin::BI__builtin_memset: {
+    MinOperationSize = MaxOperationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     DestinationSize = ComputeSizeArgument(0);
-    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
 
@@ -1417,14 +1422,12 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   case Builtin::BI__builtin_memcpy:
   case Builtin::BImemmove:
   case Builtin::BI__builtin_memmove:
-  case Builtin::BImemset:
-  case Builtin::BI__builtin_memset:
   case Builtin::BImempcpy:
   case Builtin::BI__builtin_mempcpy: {
-    DiagID = diag::warn_fortify_source_overflow;
-    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
+    MinOperationSize = MaxOperationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     DestinationSize = ComputeSizeArgument(0);
-    IsTriggered = CompareSizeSourceToDest() > 0;
+    SourceSize = ComputeSizeArgument(1);
     break;
   }
 
@@ -1436,10 +1439,9 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   case Builtin::BI__builtin_readlinkat:
   case Builtin::BIgetcwd:
   case Builtin::BI__builtin_getcwd: {
-    DiagID = diag::warn_fortify_source_size_mismatch;
-    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     DestinationSize = ComputeSizeArgument(TheCall->getNumArgs() - 2);
-    IsTriggered = CompareSizeSourceToDest() > 0;
+    MaxOperationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
     break;
   }
 
@@ -1447,20 +1449,17 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   case Builtin::BI__builtin_pread:
   case Builtin::BIpread64:
   case Builtin::BI__builtin_pread64: {
-    DiagID = diag::warn_fortify_source_size_mismatch;
-    SourceSize = ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
     DestinationSize = ComputeSizeArgument(TheCall->getNumArgs() - 3);
-    IsTriggered = CompareSizeSourceToDest() > 0;
+    MaxOperationSize =
+        ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
     break;
   }
 
   case Builtin::BIwrite:
   case Builtin::BI__builtin_write: {
-    DiagID = diag::warn_fortify_destination_size_mismatch;
     SourceSize = ComputeSizeArgument(TheCall->getNumArgs() - 2);
-    DestinationSize =
+    MaxOperationSize =
         ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 1);
-    IsTriggered = CompareSizeSourceToDest() < 0;
     break;
   }
 
@@ -1468,11 +1467,9 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   case Builtin::BI__builtin_pwrite:
   case Builtin::BIpwrite64:
   case Builtin::BI__builtin_pwrite64: {
-    DiagID = diag::warn_fortify_destination_size_mismatch;
     SourceSize = ComputeSizeArgument(TheCall->getNumArgs() - 3);
-    DestinationSize =
+    MaxOperationSize =
         ComputeExplicitObjectSizeArgument(TheCall->getNumArgs() - 2);
-    IsTriggered = CompareSizeSourceToDest() < 0;
     break;
   }
 
@@ -1480,12 +1477,11 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
   case Builtin::BI__builtin_snprintf:
   case Builtin::BIvsnprintf:
   case Builtin::BI__builtin_vsnprintf: {
-    DiagID = diag::warn_fortify_source_size_mismatch;
-    SourceSize = ComputeExplicitObjectSizeArgument(1);
+    MaxOperationSize = ComputeExplicitObjectSizeArgument(1);
     const auto *FormatExpr = TheCall->getArg(2)->IgnoreParenImpCasts();
     StringRef FormatStrRef;
     size_t StrLen;
-    if (SourceSize &&
+    if (MaxOperationSize &&
         ProcessFormatStringLiteral(FormatExpr, FormatStrRef, StrLen, Context)) 
{
       EstimateSizeFormatHandler H(FormatStrRef);
       const char *FormatBytes = FormatStrRef.data();
@@ -1495,13 +1491,13 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
         llvm::APSInt FormatSize =
             llvm::APSInt::getUnsigned(H.getSizeLowerBound())
                 .extOrTrunc(SizeTypeWidth);
-        if (FormatSize > *SourceSize && *SourceSize != 0) {
+        if (FormatSize > *MaxOperationSize && *MaxOperationSize != 0) {
           unsigned TruncationDiagID =
               H.isKernelCompatible() ? diag::warn_format_truncation
                                      : 
diag::warn_format_truncation_non_kprintf;
           SmallString<16> SpecifiedSizeStr;
           SmallString<16> FormatSizeStr;
-          SourceSize->toString(SpecifiedSizeStr, /*Radix=*/10);
+          MaxOperationSize->toString(SpecifiedSizeStr, /*Radix=*/10);
           FormatSize.toString(FormatSizeStr, /*Radix=*/10);
           DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
                               PDiag(TruncationDiagID)
@@ -1511,23 +1507,57 @@ void 
Sema::checkFortifiedBuiltinMemoryFunction(FunctionDecl *FD,
       }
     }
     DestinationSize = ComputeSizeArgument(0);
-    IsTriggered = CompareSizeSourceToDest() > 0;
     break;
   }
   }
 
-  if (!IsTriggered)
-    return;
-
   std::string FunctionName = GetFunctionName();
+  SmallString<16> MaxOpStr;
+  SmallString<16> MinOpStr;
+
+  if (MinOperationSize)
+    MinOperationSize->toString(MinOpStr, /*Radix=*/10);
+  if (MaxOperationSize)
+    MaxOperationSize->toString(MaxOpStr, /*Radix=*/10);
+
+  if (DestinationSize) {
+    SmallString<16> DestinationStr;
+    DestinationSize->toString(DestinationStr, /*Radix=*/10);
+    // Check for definate overflow
+    if (MinOperationSize &&
+        llvm::APSInt::compareValues(*MinOperationSize, *DestinationSize) > 0) {
+      DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
+                          PDiag(DiagOverflowID)
+                              << FunctionName << DestinationStr << MinOpStr);
+    }
+    // Check for possible overflow
+    else if (MaxOperationSize && llvm::APSInt::compareValues(
+                                     *MaxOperationSize, *DestinationSize) > 0) 
{
+      DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
+                          PDiag(DiagMayOverflowID)
+                              << FunctionName << DestinationStr << MaxOpStr);
+    }
+  }
+
+  if (SourceSize) {
+    SmallString<16> SourceStr;
+    SourceSize->toString(SourceStr, /*Radix=*/10);
+    // Check for definate over-read
+    if (MinOperationSize &&
+        llvm::APSInt::compareValues(*MinOperationSize, *SourceSize) > 0) {
+      DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
+                          PDiag(DiagOverReadID)
+                              << FunctionName << SourceStr << MinOpStr);
 
-  SmallString<16> DestinationStr;
-  SmallString<16> SourceStr;
-  DestinationSize->toString(DestinationStr, /*Radix=*/10);
-  SourceSize->toString(SourceStr, /*Radix=*/10);
-  DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
-                      PDiag(DiagID)
-                          << FunctionName << DestinationStr << SourceStr);
+    }
+    // Check for possible over-read
+    else if (MaxOperationSize &&
+             llvm::APSInt::compareValues(*MaxOperationSize, *SourceSize) > 0) {
+      DiagRuntimeBehavior(TheCall->getBeginLoc(), TheCall,
+                          PDiag(DiagMayOverReadID)
+                              << FunctionName << SourceStr << MaxOpStr);
+    }
+  }
 }
 
 static bool BuiltinSEHScopeCheck(Sema &SemaRef, CallExpr *TheCall,
diff --git a/clang/test/Sema/builtin-memcpy.c b/clang/test/Sema/builtin-memcpy.c
index 2a55e78034a02..af7f2034f3c30 100644
--- a/clang/test/Sema/builtin-memcpy.c
+++ b/clang/test/Sema/builtin-memcpy.c
@@ -7,7 +7,8 @@
 /// Zero-sized structs should not crash.
 int b() {
   struct {      } a[10];
-  __builtin_memcpy(&a[2], a, 2); // c-warning {{buffer has size 0, but size 
argument is 2}}
+  __builtin_memcpy(&a[2], a, 2); // c-warning {{buffer has size 0, but size 
argument is 2}} \
+                                 // c-warning {{buffer has size 0, but size 
argument is 2}}
   return 0;
 }
 
diff --git a/clang/test/Sema/warn-fortify-source.c 
b/clang/test/Sema/warn-fortify-source.c
index 5d4a8d81b0b3e..62068361b92f9 100644
--- a/clang/test/Sema/warn-fortify-source.c
+++ b/clang/test/Sema/warn-fortify-source.c
@@ -30,6 +30,8 @@ void call_memcpy(void) {
   char dst[10];
   char src[20];
   memcpy(dst, src, 20); // expected-warning {{memcpy' will always overflow; 
destination buffer has size 10, but size argument is 20}}
+  memcpy(dst, src, 21); // expected-warning {{memcpy' will always overflow; 
destination buffer has size 10, but size argument is 21}} \
+                          // expected-warning {{memcpy' will always over-read; 
source buffer has size 20, but size argument is 21}}
 
   if (sizeof(dst) == sizeof(src))
     memcpy(dst, src, 20); // no warning, unreachable
@@ -43,18 +45,29 @@ void call_memcpy_type(void) {
   struct pair p;
   char buf[20];
   memcpy(&p.first, buf, 20); // expected-warning {{memcpy' will always 
overflow; destination buffer has size 8, but size argument is 20}}
+  memcpy(&p.first, buf, 21); // expected-warning {{memcpy' will always 
overflow; destination buffer has size 8, but size argument is 21}} \
+                                        // expected-warning {{memcpy' will 
always over-read; source buffer has size 20, but size argument is 21}}
+}
+
+void call_memcpy_chk(void) {
+  char dst[10];
+  char src[10];
+  __builtin___memcpy_chk(dst, src, 10, 10);
+  __builtin___memcpy_chk(dst, src, 10, 9); // expected-warning {{memcpy' will 
always overflow; destination buffer has size 9, but size argument is 10}}
 }
 
 void call_strncat(void) {
   char s1[10], s2[20];
   __builtin_strncat(s2, s1, 20);
   __builtin_strncat(s1, s2, 20); // expected-warning {{'strncat' size argument 
is too large; destination buffer has size 10, but size argument is 20}}
+  __builtin_strncat(s1, "abcd", 20); // expected-warning {{'strncat' size 
argument is too large; destination buffer has size 10, but size argument is 20}}
 }
 
 void call_strncpy(void) {
   char s1[10], s2[20];
   __builtin_strncpy(s2, s1, 20);
   __builtin_strncpy(s1, s2, 20); // expected-warning {{'strncpy' size argument 
is too large; destination buffer has size 10, but size argument is 20}}
+  __builtin_strncpy(s1, "abcd", 20); // expected-warning {{'strncpy' size 
argument is too large; destination buffer has size 10, but size argument is 20}}
 }
 
 void call_stpncpy(void) {
@@ -84,9 +97,17 @@ void call_stpcpy(void) {
   __builtin_stpcpy(dst2, src); // expected-warning {{'stpcpy' will always 
overflow; destination buffer has size 4, but the source string has length 5 
(including NUL byte)}}
 }
 
+void call_stpcpy_chk(void) {
+  const char *const src = "abcd";
+  char dst1[5];
+  __builtin___stpcpy_chk(dst1, src, 5);
+  __builtin___stpcpy_chk(dst1, src, 4); // expected-warning {{'stpcpy' will 
always overflow; destination buffer has size 4, but the source string has 
length 5 (including NUL byte)}}
+}
+
 void call_memmove(void) {
   char s1[10], s2[20];
-  __builtin_memmove(s2, s1, 20);
+  __builtin_memmove(s2, s1, 10);
+  __builtin_memmove(s2, s1, 20); // expected-warning {{'memmove' will always 
over-read; source buffer has size 10, but size argument is 20}}
   __builtin_memmove(s1, s2, 20); // expected-warning {{'memmove' will always 
overflow; destination buffer has size 10, but size argument is 20}}
 }
 
@@ -290,11 +311,23 @@ template <int A, int B>
 void call_memcpy_dep() {
   char bufferA[A];
   char bufferB[B];
-  memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always 
overflow; destination buffer has size 9, but size argument is 10}}
+  if (sizeof(bufferA) < 10 && sizeof(bufferB) < 10) {
+    memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always 
overflow; destination buffer has size 9, but size argument is 10}} \
+                                  // expected-warning{{'memcpy' will always 
over-read; source buffer has size 9, but size argument is 10}}
+  } else if (sizeof(bufferA) < 10) {
+    memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always 
overflow; destination buffer has size 9, but size argument is 10}}
+  } else if (sizeof(bufferB) < 10) {
+    memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always 
over-read; source buffer has size 9, but size argument is 10}}
+  } else {
+    memcpy(bufferA, bufferB, 10);
+  }
+
 }
 
 void call_call_memcpy() {
-  call_memcpy_dep<10, 9>();
+  call_memcpy_dep<10, 10>();
+  call_memcpy_dep<10, 9>(); // expected-note {{in instantiation of function 
template specialization 'call_memcpy_dep<10, 9>' requested here}}
   call_memcpy_dep<9, 10>(); // expected-note {{in instantiation of function 
template specialization 'call_memcpy_dep<9, 10>' requested here}}
+  call_memcpy_dep<9, 9>(); // expected-note {{in instantiation of function 
template specialization 'call_memcpy_dep<9, 9>' requested here}}
 }
 #endif

>From fcd697de00bb6bd0db9da2645c470b09c67c702f Mon Sep 17 00:00:00 2001
From: Colin Kinloch <[email protected]>
Date: Mon, 3 Nov 2025 20:46:15 +0000
Subject: [PATCH 3/7] [clang][Sema] Avoid builtin redecleration for asm-label
 test

As `readlink` is now defined as bultin it throws an error when
redeclared with a different type: "incompatible redeclaration of library
function function 'readlink'"

As `sync` has the type `void(void)` it
this issue should not happen in the future.
---
 clang/test/Sema/asm-label.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/test/Sema/asm-label.c b/clang/test/Sema/asm-label.c
index eb0259863b2b2..a8b6afc252c2d 100644
--- a/clang/test/Sema/asm-label.c
+++ b/clang/test/Sema/asm-label.c
@@ -25,6 +25,6 @@ int z __asm__("zooms");  // expected-error{{conflicting asm 
label}}
 
 
 // No diagnostics on the following.
-void __real_readlink(void) __asm("readlink");
-void readlink(void) __asm("__protected_readlink");
-void readlink(void) { __real_readlink(); }
+void __real_sync(void) __asm("sync");
+void sync(void) __asm("__protected_sync");
+void sync(void) { __real_sync(); }

>From af4cb4d73a977ab4546de2c4b863802d81c8bd40 Mon Sep 17 00:00:00 2001
From: Colin Kinloch <[email protected]>
Date: Thu, 6 Nov 2025 00:00:53 +0000
Subject: [PATCH 4/7] [clang][Sema] Use relative line number for template
 warnings

---
 clang/test/Sema/warn-fortify-source.c | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

diff --git a/clang/test/Sema/warn-fortify-source.c 
b/clang/test/Sema/warn-fortify-source.c
index 62068361b92f9..f0e9b2fc9c1db 100644
--- a/clang/test/Sema/warn-fortify-source.c
+++ b/clang/test/Sema/warn-fortify-source.c
@@ -311,17 +311,15 @@ template <int A, int B>
 void call_memcpy_dep() {
   char bufferA[A];
   char bufferB[B];
+  memcpy(bufferA, bufferB, 10);
   if (sizeof(bufferA) < 10 && sizeof(bufferB) < 10) {
-    memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always 
overflow; destination buffer has size 9, but size argument is 10}} \
-                                  // expected-warning{{'memcpy' will always 
over-read; source buffer has size 9, but size argument is 10}}
+    // expected-warning@-2{{'memcpy' will always overflow; destination buffer 
has size 9, but size argument is 10}}
+    // expected-warning@-3{{'memcpy' will always over-read; source buffer has 
size 9, but size argument is 10}}
   } else if (sizeof(bufferA) < 10) {
-    memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always 
overflow; destination buffer has size 9, but size argument is 10}}
+    // expected-warning@-5{{'memcpy' will always overflow; destination buffer 
has size 9, but size argument is 10}}
   } else if (sizeof(bufferB) < 10) {
-    memcpy(bufferA, bufferB, 10); // expected-warning{{'memcpy' will always 
over-read; source buffer has size 9, but size argument is 10}}
-  } else {
-    memcpy(bufferA, bufferB, 10);
+    // expected-warning@-7{{'memcpy' will always over-read; source buffer has 
size 9, but size argument is 10}}
   }
-
 }
 
 void call_call_memcpy() {

>From 85c6e482ed41bd907f8d481d9263da447510c11b Mon Sep 17 00:00:00 2001
From: Colin Kinloch <[email protected]>
Date: Thu, 6 Nov 2025 01:58:37 +0000
Subject: [PATCH 5/7] [clang][test] Add over-read warnings to analysis tests

---
 clang/test/Analysis/bstring.c | 15 +++++++++++++++
 clang/test/Analysis/malloc.c  |  2 +-
 clang/test/Analysis/pr22954.c |  3 ++-
 3 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/clang/test/Analysis/bstring.c b/clang/test/Analysis/bstring.c
index f015e0b5d9fb7..5ccecf805e5bb 100644
--- a/clang/test/Analysis/bstring.c
+++ b/clang/test/Analysis/bstring.c
@@ -93,6 +93,9 @@ void memcpy1 (void) {
   char dst[10];
 
   memcpy(dst, src, 5); // expected-warning{{Memory copy function accesses 
out-of-bound array element}}
+#ifndef VARIANT
+  // expected-warning@-2{{memcpy' will always over-read; source buffer has 
size 4, but size argument is 5}}
+#endif
 }
 
 void memcpy2 (void) {
@@ -117,6 +120,9 @@ void memcpy4 (void) {
   char dst[10];
 
   memcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses 
out-of-bound array element}}
+#ifndef VARIANT
+  // expected-warning@-2{{memcpy' will always over-read; source buffer has 
size 2, but size argument is 3}}
+#endif
 }
 
 void memcpy5(void) {
@@ -219,6 +225,9 @@ void mempcpy1 (void) {
   char dst[10];
 
   mempcpy(dst, src, 5); // expected-warning{{Memory copy function accesses 
out-of-bound array element}}
+#ifndef VARIANT
+  // expected-warning@-2{{mempcpy' will always over-read; source buffer has 
size 4, but size argument is 5}}
+#endif
 }
 
 void mempcpy2 (void) {
@@ -243,6 +252,9 @@ void mempcpy4 (void) {
   char dst[10];
 
   mempcpy(dst+2, src+2, 3); // expected-warning{{Memory copy function accesses 
out-of-bound array element}}
+#ifndef VARIANT
+  // expected-warning@-2{{mempcpy' will always over-read; source buffer has 
size 2, but size argument is 3}}
+#endif
 }
 
 void mempcpy5(void) {
@@ -384,6 +396,9 @@ void memmove1 (void) {
   char dst[10];
 
   memmove(dst, src, 5); // expected-warning{{out-of-bound}}
+#ifndef VARIANT
+  // expected-warning@-2{{memmove' will always over-read; source buffer has 
size 4, but size argument is 5}}
+#endif
 }
 
 void memmove2 (void) {
diff --git a/clang/test/Analysis/malloc.c b/clang/test/Analysis/malloc.c
index 92b47bc3b5e9a..1286320bd4e2d 100644
--- a/clang/test/Analysis/malloc.c
+++ b/clang/test/Analysis/malloc.c
@@ -879,7 +879,7 @@ void doNotInvalidateWhenPassedToSystemCalls(char *s) {
 // Treat source buffer contents as escaped.
 void escapeSourceContents(char *s) {
   char *p = malloc(12);
-  memcpy(s, &p, 12); // no warning
+  memcpy(s, &p, 12); // expected-warning{{memcpy' will always over-read; 
source buffer has size}}
 
   void *p1 = malloc(7);
   char *a;
diff --git a/clang/test/Analysis/pr22954.c b/clang/test/Analysis/pr22954.c
index b5f8aeb2a5ca6..bfb4ba63eb4fe 100644
--- a/clang/test/Analysis/pr22954.c
+++ b/clang/test/Analysis/pr22954.c
@@ -536,7 +536,8 @@ int f262(void) {
   struct aa a262 = {{1, 2, 3, 4}, 0};
   a262.s2 = strdup("hello");
   char input[] = {'a', 'b', 'c', 'd'};
-  memcpy(a262.s1, input, -1); // expected-warning{{'memcpy' will always 
overflow; destination buffer has size 16, but size argument is 
18446744073709551615}}
+  memcpy(a262.s1, input, -1); // expected-warning{{'memcpy' will always 
overflow; destination buffer has size 16, but size argument is 
18446744073709551615}} \
+                                         // expected-warning{{'memcpy' will 
always over-read; source buffer has size 4, but size argument is 
18446744073709551615}}
   clang_analyzer_eval(a262.s1[0] == 1); // expected-warning{{UNKNOWN}}\
   expected-warning{{Potential leak of memory pointed to by 'a262.s2'}}
   clang_analyzer_eval(a262.s1[1] == 1); // expected-warning{{UNKNOWN}}

>From 86f4dba491bbc4c59c87c6c33783257963d6d5e1 Mon Sep 17 00:00:00 2001
From: Colin Kinloch <[email protected]>
Date: Thu, 6 Nov 2025 01:59:31 +0000
Subject: [PATCH 6/7] [clang][test] Use __signed_size_t for function summaries

---
 clang/test/Analysis/std-c-library-functions-POSIX.c | 4 ++--
 clang/test/Analysis/std-c-library-functions.c       | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/Analysis/std-c-library-functions-POSIX.c 
b/clang/test/Analysis/std-c-library-functions-POSIX.c
index f6d88e6c1502d..462bbf5d8e5de 100644
--- a/clang/test/Analysis/std-c-library-functions-POSIX.c
+++ b/clang/test/Analysis/std-c-library-functions-POSIX.c
@@ -98,8 +98,8 @@
 // CHECK: Loaded summary for: void *mmap64(void *addr, size_t length, int 
prot, int flags, int fd, off64_t offset)
 // CHECK: Loaded summary for: int pipe(int fildes[2])
 // CHECK: Loaded summary for: off_t lseek(int fildes, off_t offset, int whence)
-// CHECK: Loaded summary for: ssize_t readlink(const char *restrict path, char 
*restrict buf, size_t bufsize)
-// CHECK: Loaded summary for: ssize_t readlinkat(int fd, const char *restrict 
path, char *restrict buf, size_t bufsize)
+// CHECK: Loaded summary for: __signed_size_t readlink(const char *restrict 
path, char *restrict buf, size_t bufsize)
+// CHECK: Loaded summary for: __signed_size_t readlinkat(int fd, const char 
*restrict path, char *restrict buf, size_t bufsize)
 // CHECK: Loaded summary for: int renameat(int olddirfd, const char *oldpath, 
int newdirfd, const char *newpath)
 // CHECK: Loaded summary for: char *realpath(const char *restrict file_name, 
char *restrict resolved_name)
 // CHECK: Loaded summary for: int execv(const char *path, char *const argv[])
diff --git a/clang/test/Analysis/std-c-library-functions.c 
b/clang/test/Analysis/std-c-library-functions.c
index b5f663493a676..45ca1c69f89e3 100644
--- a/clang/test/Analysis/std-c-library-functions.c
+++ b/clang/test/Analysis/std-c-library-functions.c
@@ -61,8 +61,8 @@
 // CHECK-NEXT: Loaded summary for: int getchar(void)
 // CHECK-NEXT: Loaded summary for: __size_t fread(void *restrict, size_t, 
size_t, FILE *restrict)
 // CHECK-NEXT: Loaded summary for: __size_t fwrite(const void *restrict, 
size_t, size_t, FILE *restrict)
-// CHECK-NEXT: Loaded summary for: ssize_t read(int, void *, size_t)
-// CHECK-NEXT: Loaded summary for: ssize_t write(int, const void *, size_t)
+// CHECK-NEXT: Loaded summary for: __signed_size_t read(int, void *, size_t)
+// CHECK-NEXT: Loaded summary for: __signed_size_t write(int, const void *, 
size_t)
 // CHECK-NEXT: Loaded summary for: ssize_t getline(char **restrict, size_t 
*restrict, FILE *restrict)
 // CHECK-NEXT: Loaded summary for: ssize_t getdelim(char **restrict, size_t 
*restrict, int, FILE *restrict)
 // CHECK-NEXT: Loaded summary for: char *getenv(const char *)

>From f74be7d3255bbac7b0d5aba61f3f97634327f375 Mon Sep 17 00:00:00 2001
From: Colin Kinloch <[email protected]>
Date: Thu, 6 Nov 2025 02:02:59 +0000
Subject: [PATCH 7/7] [clang][test] Rename function to avoid redeclaration

---
 clang/test/Analysis/array-struct.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/Analysis/array-struct.c 
b/clang/test/Analysis/array-struct.c
index f0eba86fe71bf..691bb1348a44f 100644
--- a/clang/test/Analysis/array-struct.c
+++ b/clang/test/Analysis/array-struct.c
@@ -175,12 +175,12 @@ void f17(void) {
     x = 1;
 }
 
-void read(char*);
+void readp(char*);
 
 void f18(void) {
   char *q;
   char *p = (char *) __builtin_alloca(10);
-  read(p);
+  readp(p);
   q = p;
   q++;
   if (*q) { // no-warning

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to