https://github.com/kees created https://github.com/llvm/llvm-project/pull/214827

-fsanitize-kcfi-hash= is a CC1Option that selects the hash algorithm used to 
derive KCFI type IDs (xxHash64 or FNV-1a), but the driver never claimed or 
forwarded it. As a result, invocations like

  clang -fsanitize=kcfi -fsanitize-kcfi-hash=FNV-1a foo.c

silently dropped the flag with an "argument unused during compilation" warning; 
users had to route it through -Xclang to reach cc1. This is particularly 
awkward for build systems (e.g. the Linux kernel) that want to select FNV-1a 
for -fsanitize=kcfi builds.

Handle the option in SanitizerArgs alongside -fsanitize-kcfi-arity: capture the 
last-specified value when KCFI is enabled and forward it to cc1 as 
-fsanitize-kcfi-hash=<value>. Values are still validated by cc1's 
tablegen-driven Values<"xxHash64,FNV-1a"> checker, so bad values produce the 
usual "invalid value" diagnostic. When -fsanitize=kcfi is not specified, the 
flag remains unclaimed and triggers -Wunused-command-line-argument, matching 
the behavior of the sibling -fsanitize-kcfi-arity option.

Extend clang/test/Driver/fsanitize-cfi.c (which already covers other KCFI-mode 
cc1 arg forwarding, e.g. -fsanitize-cfi-icall-generalize- pointers) with 
forwarding, last-wins, invalid-value, and unused-when-no-KCFI cases for both 
-fsanitize-kcfi-hash= and -fsanitize-kcfi-arity. The latter had no prior 
driver-side coverage.

Assisted-by: Claude Opus 4.7

>From 751c11296b301750da0a26d4363d4ef313ad9123 Mon Sep 17 00:00:00 2001
From: Kees Cook <[email protected]>
Date: Fri, 7 Aug 2026 11:37:22 -0700
Subject: [PATCH] [Driver][KCFI] Forward -fsanitize-kcfi-hash= to cc1

-fsanitize-kcfi-hash= is a CC1Option that selects the hash algorithm
used to derive KCFI type IDs (xxHash64 or FNV-1a), but the driver
never claimed or forwarded it. As a result, invocations like

  clang -fsanitize=kcfi -fsanitize-kcfi-hash=FNV-1a foo.c

silently dropped the flag with an "argument unused during compilation"
warning; users had to route it through -Xclang to reach cc1. This is
particularly awkward for build systems (e.g. the Linux kernel) that
want to select FNV-1a for -fsanitize=kcfi builds.

Handle the option in SanitizerArgs alongside -fsanitize-kcfi-arity:
capture the last-specified value when KCFI is enabled and forward it
to cc1 as -fsanitize-kcfi-hash=<value>. Values are still validated by
cc1's tablegen-driven Values<"xxHash64,FNV-1a"> checker, so bad
values produce the usual "invalid value" diagnostic. When
-fsanitize=kcfi is not specified, the flag remains unclaimed and
triggers -Wunused-command-line-argument, matching the behavior of
the sibling -fsanitize-kcfi-arity option.

Extend clang/test/Driver/fsanitize-cfi.c (which already covers other
KCFI-mode cc1 arg forwarding, e.g. -fsanitize-cfi-icall-generalize-
pointers) with forwarding, last-wins, invalid-value, and
unused-when-no-KCFI cases for both -fsanitize-kcfi-hash= and
-fsanitize-kcfi-arity. The latter had no prior driver-side coverage.

Assisted-by: Claude Opus 4.7
---
 clang/include/clang/Driver/SanitizerArgs.h |  1 +
 clang/lib/Driver/SanitizerArgs.cpp         |  6 +++++
 clang/test/Driver/fsanitize-cfi.c          | 28 ++++++++++++++++++++++
 3 files changed, 35 insertions(+)

diff --git a/clang/include/clang/Driver/SanitizerArgs.h 
b/clang/include/clang/Driver/SanitizerArgs.h
index 6a01b3e36d44c..b0ab97a2d5d45 100644
--- a/clang/include/clang/Driver/SanitizerArgs.h
+++ b/clang/include/clang/Driver/SanitizerArgs.h
@@ -49,6 +49,7 @@ class SanitizerArgs {
   bool CfiICallNormalizeIntegers = false;
   bool CfiCanonicalJumpTables = false;
   bool KcfiArity = false;
+  std::string KcfiHash;
   int AsanFieldPadding = 0;
   bool SharedRuntime = false;
   bool StableABI = false;
diff --git a/clang/lib/Driver/SanitizerArgs.cpp 
b/clang/lib/Driver/SanitizerArgs.cpp
index c77ba78122a81..07d9ab9594482 100644
--- a/clang/lib/Driver/SanitizerArgs.cpp
+++ b/clang/lib/Driver/SanitizerArgs.cpp
@@ -964,6 +964,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
 
     KcfiArity = Args.hasArg(options::OPT_fsanitize_kcfi_arity);
 
+    if (const Arg *A = Args.getLastArg(options::OPT_fsanitize_kcfi_hash_EQ))
+      KcfiHash = A->getValue();
+
     if (AllAddedKinds & SanitizerKind::CFI && DiagnoseErrors)
       D.Diag(diag::err_drv_argument_not_allowed_with)
           << "-fsanitize=kcfi"
@@ -1573,6 +1576,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const 
llvm::opt::ArgList &Args,
     CmdArgs.push_back("-fsanitize-kcfi-arity");
   }
 
+  if (!KcfiHash.empty())
+    CmdArgs.push_back(Args.MakeArgString("-fsanitize-kcfi-hash=" + KcfiHash));
+
   if (CfiCanonicalJumpTables)
     CmdArgs.push_back("-fsanitize-cfi-canonical-jump-tables");
 
diff --git a/clang/test/Driver/fsanitize-cfi.c 
b/clang/test/Driver/fsanitize-cfi.c
index c58ad3b8c2f1c..def3e61908ee7 100644
--- a/clang/test/Driver/fsanitize-cfi.c
+++ b/clang/test/Driver/fsanitize-cfi.c
@@ -96,3 +96,31 @@
 
 // RUN: not %clang --target=x86_64-linux-gnu -fsanitize=kcfi,function %s -### 
2>&1 | FileCheck %s --check-prefix=CHECK-KCFI-FUNCTION
 // CHECK-KCFI-FUNCTION: error: invalid argument '-fsanitize=kcfi' not allowed 
with '-fsanitize=function'
+
+// -fsanitize-kcfi-arity is forwarded to cc1 when KCFI is enabled.
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=kcfi -fsanitize-kcfi-arity 
%s -### 2>&1 | FileCheck %s --check-prefix=CHECK-KCFI-ARITY
+// CHECK-KCFI-ARITY: "-fsanitize-kcfi-arity"
+
+// Without -fsanitize=kcfi, -fsanitize-kcfi-arity is unused.
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize-kcfi-arity -c %s -o 
/dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-KCFI-ARITY-UNUSED
+// CHECK-KCFI-ARITY-UNUSED: warning: argument unused during compilation: 
'-fsanitize-kcfi-arity'
+
+// -fsanitize-kcfi-hash= is forwarded to cc1 when KCFI is enabled.
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=kcfi 
-fsanitize-kcfi-hash=FNV-1a %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-KCFI-HASH-FNV
+// CHECK-KCFI-HASH-FNV: "-fsanitize-kcfi-hash=FNV-1a"
+
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=kcfi 
-fsanitize-kcfi-hash=xxHash64 %s -### 2>&1 | FileCheck %s 
--check-prefix=CHECK-KCFI-HASH-XXHASH
+// CHECK-KCFI-HASH-XXHASH: "-fsanitize-kcfi-hash=xxHash64"
+
+// If -fsanitize-kcfi-hash= is given more than once, the last value wins.
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize=kcfi 
-fsanitize-kcfi-hash=xxHash64 -fsanitize-kcfi-hash=FNV-1a %s -### 2>&1 | 
FileCheck %s --check-prefix=CHECK-KCFI-HASH-LAST
+// CHECK-KCFI-HASH-LAST:     "-fsanitize-kcfi-hash=FNV-1a"
+// CHECK-KCFI-HASH-LAST-NOT: "-fsanitize-kcfi-hash=xxHash64"
+
+// Invalid values are diagnosed by cc1 (driver forwards verbatim).
+// RUN: not %clang --target=x86_64-linux-gnu -fsanitize=kcfi 
-fsanitize-kcfi-hash=bogus -c %s 2>&1 | FileCheck %s 
--check-prefix=CHECK-KCFI-HASH-BAD
+// CHECK-KCFI-HASH-BAD: error: invalid value 'bogus' in 
'-fsanitize-kcfi-hash=bogus'
+
+// Without -fsanitize=kcfi, -fsanitize-kcfi-hash= is unused.
+// RUN: %clang --target=x86_64-linux-gnu -fsanitize-kcfi-hash=FNV-1a -c %s -o 
/dev/null 2>&1 | FileCheck %s --check-prefix=CHECK-KCFI-HASH-UNUSED
+// CHECK-KCFI-HASH-UNUSED: warning: argument unused during compilation: 
'-fsanitize-kcfi-hash=FNV-1a'

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

Reply via email to