[clang] [clang][ptrauth] Warn about the use of a weak signing schema (PR #157779)
Martin Balao Alonso via cfe-commits
cfe-commits at lists.llvm.org
Thu Sep 11 09:38:12 PDT 2025
https://github.com/martinuy updated https://github.com/llvm/llvm-project/pull/157779
>From 8fe991fb658d02351b2e819b275de1e821075f03 Mon Sep 17 00:00:00 2001
From: Martin Balao Alonso <martin.uy at apple.com>
Date: Tue, 9 Sep 2025 18:29:38 -0700
Subject: [PATCH 1/3] [clang][ptrauth] Warn about the use of a weak signing
schema
In this change we added the -Wptrauth-weak-schema diagnostic (enabled by
default on targets that support pointer authentication) to warn about the
use of a weak signing schema for function pointers stored in global variables
with internal linkage.
rdar://159299739
---
clang/include/clang/Basic/DiagnosticGroups.td | 1 +
.../clang/Basic/DiagnosticSemaKinds.td | 4 ++
clang/lib/Sema/SemaDecl.cpp | 9 +++
clang/test/Sema/ptrauth-weak-schema.c | 68 +++++++++++++++++++
4 files changed, 82 insertions(+)
create mode 100644 clang/test/Sema/ptrauth-weak-schema.c
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 0c994e0b5ca4d..de10c39a4ac3c 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1072,6 +1072,7 @@ def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments", [VariadicMacroArgumentsOmitted]>;
def MisleadingIndentation : DiagGroup<"misleading-indentation">;
def PtrAuthNullPointers : DiagGroup<"ptrauth-null-pointers">;
+def PtrAuthWeakSchema : DiagGroup<"ptrauth-weak-schema">;
// This covers both the deprecated case (in C++98)
// and the extension case (in C++11 onwards).
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b0e669cd3560d..e1dc8ab20d6f4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1046,6 +1046,10 @@ def err_ptrauth_address_discrimination_invalid : Error<
def err_ptrauth_extra_discriminator_invalid : Error<
"invalid extra discriminator flag '%0'; '__ptrauth' requires a value between "
"'0' and '%1'">;
+def warn_ptrauth_weak_schema
+ : Warning<"internal variable %0 is using a weak signing schema for pointer "
+ "authentication">,
+ InGroup<PtrAuthWeakSchema>;
/// main()
// static main() is not an error in C, just in C++.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7c1459e320167..a8eb1188916b7 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8357,6 +8357,15 @@ NamedDecl *Sema::ActOnVariableDeclarator(
D.isFunctionDefinition());
}
+ // Warn about the use of a weak pointer authentication schema on a variable
+ // with internal linkage.
+ if (getLangOpts().PointerAuthCalls && NewVD->isFunctionPointerType() &&
+ !isExternallyVisible(NewVD->getLinkageInternal())) {
+ PointerAuthQualifier Q = NewVD->getType().getQualifiers().getPointerAuth();
+ if (!Q || (!Q.isAddressDiscriminated() && Q.getExtraDiscriminator() == 0))
+ Diag(NewVD->getLocation(), diag::warn_ptrauth_weak_schema) << NewVD;
+ }
+
if (NewTemplate) {
if (NewVD->isInvalidDecl())
NewTemplate->setInvalidDecl();
diff --git a/clang/test/Sema/ptrauth-weak-schema.c b/clang/test/Sema/ptrauth-weak-schema.c
new file mode 100644
index 0000000000000..792ff9f99627c
--- /dev/null
+++ b/clang/test/Sema/ptrauth-weak-schema.c
@@ -0,0 +1,68 @@
+// RUN: %clang_cc1 -triple arm64e-apple-ios -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple arm64e-apple-ios -DNO_PTRAUTH -fsyntax-only -verify %s
+
+#if defined(NO_PTRAUTH)
+
+#define FN_PTR_AUTH(address_diversity, constant_discriminator)
+// expected-no-diagnostics
+
+#else // !defined(NO_PTRAUTH)
+
+#if !__has_extension(ptrauth_qualifier)
+#error __ptrauth qualifier not enabled
+#endif
+
+#include <ptrauth.h>
+
+#define FN_PTR_AUTH(address_diversity, constant_discriminator) \
+ __ptrauth(ptrauth_key_function_pointer, address_diversity, constant_discriminator)
+
+#endif // defined(NO_PTRAUTH)
+
+// Global variables with external linkage and weak pointer authentication should
+// not raise any warning.
+extern void(* g1_external_weak)(void);
+void(* FN_PTR_AUTH(0, 0) g2_external_weak)(void);
+
+// Global variables with internal linkage and strong pointer authentication
+// should not raise any warning.
+static void(* FN_PTR_AUTH(1, 65535) g1_internal_strong)(void);
+static void(* FN_PTR_AUTH(0, 65535) g2_internal_strong)(void);
+static void(* FN_PTR_AUTH(1, 0) g3_internal_strong)(void);
+
+#if !defined(NO_PTRAUTH)
+// Global variables with internal linkage and weak pointer authentication should
+// raise a warning.
+static void(* g1_internal_weak)(void);
+// expected-warning at -1 {{internal variable 'g1_internal_weak' is using a weak signing schema for pointer authentication}}
+static void(* FN_PTR_AUTH(0, 0) g2_internal_weak)(void);
+// expected-warning at -1 {{internal variable 'g2_internal_weak' is using a weak signing schema for pointer authentication}}
+
+// Assert that -Wptrauth-weak-schema silences warnings.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wptrauth-weak-schema"
+static void(* g3_internal_weak)(void);
+#pragma clang diagnostic pop
+#endif
+
+void test_local_variables(void) {
+ #pragma clang diagnostic push
+ #pragma clang diagnostic ignored "-Wunused-variable"
+
+ #if !defined(NO_PTRAUTH)
+ // Local variables (internal linkage) with weak pointer authentication
+ // should raise a warning.
+ static void(* l1_internal_weak)(void);
+ // expected-warning at -1 {{internal variable 'l1_internal_weak' is using a weak signing schema for pointer authentication}}
+ static void(* FN_PTR_AUTH(0, 0) l2_internal_weak)(void);
+ // expected-warning at -1 {{internal variable 'l2_internal_weak' is using a weak signing schema for pointer authentication}}
+ #endif
+
+ // Local variables (internal linkage) with strong pointer authentication
+ // should not raise any warning.
+ void(* FN_PTR_AUTH(1, 65535) l1_internal_strong)(void);
+ void(* FN_PTR_AUTH(0, 65535) l2_internal_strong)(void);
+ void(* FN_PTR_AUTH(1, 0) l3_internal_strong)(void);
+
+ #pragma clang diagnostic pop
+}
>From bc4d0a78e74b86b2ae490d8b7a3428a65fa66ece Mon Sep 17 00:00:00 2001
From: Martin Balao Alonso <martin.uy at apple.com>
Date: Wed, 10 Sep 2025 16:10:29 -0700
Subject: [PATCH 2/3] Changes after @ojhunt's review on 2025-09-09 (#157779)
---
clang/include/clang/AST/ASTContext.h | 9 ++---
clang/include/clang/Basic/DiagnosticGroups.td | 1 -
.../clang/Basic/DiagnosticSemaKinds.td | 7 ++--
clang/lib/Sema/SemaDecl.cpp | 10 +++---
clang/test/Sema/ptrauth-weak-schema.c | 34 ++++++-------------
5 files changed, 26 insertions(+), 35 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 1c17333b722f8..1580968e857d7 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -659,6 +659,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
return findPointerAuthContent(T) != PointerAuthContent::None;
}
+ // A simple helper function to short circuit pointer auth checks.
+ bool isPointerAuthenticationAvailable() const {
+ return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics;
+ }
+
private:
llvm::DenseMap<const CXXRecordDecl *, CXXRecordDeclRelocationInfo>
RelocatableClasses;
@@ -670,10 +675,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
AddressDiscriminatedData
};
- // A simple helper function to short circuit pointer auth checks.
- bool isPointerAuthenticationAvailable() const {
- return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics;
- }
PointerAuthContent findPointerAuthContent(QualType T) const;
mutable llvm::DenseMap<const RecordDecl *, PointerAuthContent>
RecordContainsAddressDiscriminatedPointerAuth;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index de10c39a4ac3c..0c994e0b5ca4d 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1072,7 +1072,6 @@ def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments", [VariadicMacroArgumentsOmitted]>;
def MisleadingIndentation : DiagGroup<"misleading-indentation">;
def PtrAuthNullPointers : DiagGroup<"ptrauth-null-pointers">;
-def PtrAuthWeakSchema : DiagGroup<"ptrauth-weak-schema">;
// This covers both the deprecated case (in C++98)
// and the extension case (in C++11 onwards).
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index e1dc8ab20d6f4..35bedc9349686 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1047,9 +1047,10 @@ def err_ptrauth_extra_discriminator_invalid : Error<
"invalid extra discriminator flag '%0'; '__ptrauth' requires a value between "
"'0' and '%1'">;
def warn_ptrauth_weak_schema
- : Warning<"internal variable %0 is using a weak signing schema for pointer "
- "authentication">,
- InGroup<PtrAuthWeakSchema>;
+ : Warning<"%0 has internal linkage with a %select{|default }1"
+ "pointer authentication schema that should be overridden by "
+ "%select{a|an explicit}1 schema with unique diversifiers">,
+ InGroup<DiagGroup<"ptrauth-weak-schema">>;
/// main()
// static main() is not an error in C, just in C++.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index a8eb1188916b7..7a7abf1c4b627 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8359,11 +8359,13 @@ NamedDecl *Sema::ActOnVariableDeclarator(
// Warn about the use of a weak pointer authentication schema on a variable
// with internal linkage.
- if (getLangOpts().PointerAuthCalls && NewVD->isFunctionPointerType() &&
- !isExternallyVisible(NewVD->getLinkageInternal())) {
+ if (Context.isPointerAuthenticationAvailable() &&
+ NewVD->isFunctionPointerType() && !NewVD->isExternallyVisible()) {
PointerAuthQualifier Q = NewVD->getType().getQualifiers().getPointerAuth();
- if (!Q || (!Q.isAddressDiscriminated() && Q.getExtraDiscriminator() == 0))
- Diag(NewVD->getLocation(), diag::warn_ptrauth_weak_schema) << NewVD;
+ if (!Q || (!Q.isAddressDiscriminated() && Q.getExtraDiscriminator() == 0)) {
+ Diag(NewVD->getLocation(), diag::warn_ptrauth_weak_schema)
+ << NewVD << (Q ? 0 : 1);
+ }
}
if (NewTemplate) {
diff --git a/clang/test/Sema/ptrauth-weak-schema.c b/clang/test/Sema/ptrauth-weak-schema.c
index 792ff9f99627c..e0aa89efc47ab 100644
--- a/clang/test/Sema/ptrauth-weak-schema.c
+++ b/clang/test/Sema/ptrauth-weak-schema.c
@@ -1,23 +1,16 @@
-// RUN: %clang_cc1 -triple arm64e-apple-ios -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -verify %s
-// RUN: %clang_cc1 -triple arm64e-apple-ios -DNO_PTRAUTH -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple arm64e-apple-ios -fptrauth-calls -fptrauth-intrinsics -fsyntax-only -Wno-unused-variable -verify %s
+// RUN: %clang_cc1 -triple arm64e-apple-ios -DNO_PTRAUTH -fsyntax-only -Wno-unused-variable -verify=noptrauth %s
-#if defined(NO_PTRAUTH)
-
-#define FN_PTR_AUTH(address_diversity, constant_discriminator)
-// expected-no-diagnostics
-
-#else // !defined(NO_PTRAUTH)
-
-#if !__has_extension(ptrauth_qualifier)
-#error __ptrauth qualifier not enabled
-#endif
+// noptrauth-no-diagnostics
#include <ptrauth.h>
+#if defined(NO_PTRAUTH)
+#define FN_PTR_AUTH(address_diversity, constant_discriminator)
+#else
#define FN_PTR_AUTH(address_diversity, constant_discriminator) \
__ptrauth(ptrauth_key_function_pointer, address_diversity, constant_discriminator)
-
-#endif // defined(NO_PTRAUTH)
+#endif
// Global variables with external linkage and weak pointer authentication should
// not raise any warning.
@@ -34,9 +27,9 @@ static void(* FN_PTR_AUTH(1, 0) g3_internal_strong)(void);
// Global variables with internal linkage and weak pointer authentication should
// raise a warning.
static void(* g1_internal_weak)(void);
-// expected-warning at -1 {{internal variable 'g1_internal_weak' is using a weak signing schema for pointer authentication}}
+// expected-warning at -1 {{'g1_internal_weak' has internal linkage with a default pointer authentication schema that should be overridden by an explicit schema with unique diversifiers}}
static void(* FN_PTR_AUTH(0, 0) g2_internal_weak)(void);
-// expected-warning at -1 {{internal variable 'g2_internal_weak' is using a weak signing schema for pointer authentication}}
+// expected-warning at -1 {{'g2_internal_weak' has internal linkage with a pointer authentication schema that should be overridden by a schema with unique diversifiers}}
// Assert that -Wptrauth-weak-schema silences warnings.
#pragma clang diagnostic push
@@ -46,16 +39,13 @@ static void(* g3_internal_weak)(void);
#endif
void test_local_variables(void) {
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wunused-variable"
-
#if !defined(NO_PTRAUTH)
// Local variables (internal linkage) with weak pointer authentication
// should raise a warning.
static void(* l1_internal_weak)(void);
- // expected-warning at -1 {{internal variable 'l1_internal_weak' is using a weak signing schema for pointer authentication}}
+ // expected-warning at -1 {{'l1_internal_weak' has internal linkage with a default pointer authentication schema that should be overridden by an explicit schema with unique diversifiers}}
static void(* FN_PTR_AUTH(0, 0) l2_internal_weak)(void);
- // expected-warning at -1 {{internal variable 'l2_internal_weak' is using a weak signing schema for pointer authentication}}
+ // expected-warning at -1 {{'l2_internal_weak' has internal linkage with a pointer authentication schema that should be overridden by a schema with unique diversifiers}}
#endif
// Local variables (internal linkage) with strong pointer authentication
@@ -63,6 +53,4 @@ void test_local_variables(void) {
void(* FN_PTR_AUTH(1, 65535) l1_internal_strong)(void);
void(* FN_PTR_AUTH(0, 65535) l2_internal_strong)(void);
void(* FN_PTR_AUTH(1, 0) l3_internal_strong)(void);
-
- #pragma clang diagnostic pop
}
>From 1d90050dce1de92876d1f9a4be62acf7090c7483 Mon Sep 17 00:00:00 2001
From: Martin Balao Alonso <martin.uy at apple.com>
Date: Wed, 10 Sep 2025 19:22:29 -0700
Subject: [PATCH 3/3] fixup! Changes after @ojhunt's review on 2025-09-09
(#157779)
Changes after @ojhunt's review on 2025-09-10 (#157779)
---
clang/lib/Sema/SemaDecl.cpp | 3 +--
clang/test/Sema/ptrauth-weak-schema.c | 4 ++++
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 7a7abf1c4b627..60410c05d10cb 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -8363,8 +8363,7 @@ NamedDecl *Sema::ActOnVariableDeclarator(
NewVD->isFunctionPointerType() && !NewVD->isExternallyVisible()) {
PointerAuthQualifier Q = NewVD->getType().getQualifiers().getPointerAuth();
if (!Q || (!Q.isAddressDiscriminated() && Q.getExtraDiscriminator() == 0)) {
- Diag(NewVD->getLocation(), diag::warn_ptrauth_weak_schema)
- << NewVD << (Q ? 0 : 1);
+ Diag(NewVD->getLocation(), diag::warn_ptrauth_weak_schema) << NewVD << !Q;
}
}
diff --git a/clang/test/Sema/ptrauth-weak-schema.c b/clang/test/Sema/ptrauth-weak-schema.c
index e0aa89efc47ab..f7f10be07736e 100644
--- a/clang/test/Sema/ptrauth-weak-schema.c
+++ b/clang/test/Sema/ptrauth-weak-schema.c
@@ -5,6 +5,10 @@
#include <ptrauth.h>
+#if defined(__PTRAUTH__) == defined(NO_PTRAUTH)
+#error expected pointer authentication state does not match actual
+#endif
+
#if defined(NO_PTRAUTH)
#define FN_PTR_AUTH(address_diversity, constant_discriminator)
#else
More information about the cfe-commits
mailing list