https://github.com/ojhunt created https://github.com/llvm/llvm-project/pull/172186
None >From 7c547005228cdb185fc0f5458c62d0c24e2df9b6 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <[email protected]> Date: Sat, 13 Dec 2025 00:39:04 -0800 Subject: [PATCH 1/2] start refactoring the ptrauth thingy --- clang/include/clang/AST/ASTContext.h | 28 +++++++++++------ clang/include/clang/Basic/DiagnosticGroups.td | 1 + .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/AST/ASTContext.cpp | 31 ++++++++++--------- 4 files changed, 39 insertions(+), 24 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index f64e29be3205f..271fb831406fb 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -681,7 +681,7 @@ class ASTContext : public RefCountedBase<ASTContext> { bool containsAddressDiscriminatedPointerAuth(QualType T) const { if (!isPointerAuthenticationAvailable()) return false; - return findPointerAuthContent(T) != PointerAuthContent::None; + return (findPointerAuthContent(T) & PointerAuthContent::ContainsAddressDiscriminatedData) != PointerAuthContent::ContainsNone; } /// Examines a given type, and returns whether the type itself @@ -692,7 +692,18 @@ class ASTContext : public RefCountedBase<ASTContext> { bool containsNonRelocatablePointerAuth(QualType T) { if (!isPointerAuthenticationAvailable()) return false; - return findPointerAuthContent(T) != PointerAuthContent::None; + return (findPointerAuthContent(T) & PointerAuthContent::ContainsAddressDiscriminatedData) != PointerAuthContent::ContainsNone; + } + + bool containsDefaultAuthenticatedFunctionPointer(QualType T) { + if (!isPointerAuthenticationAvailable()) + return false; + return (findPointerAuthContent(T) & PointerAuthContent::ContainsDefaultAuthenticatedFunction) != PointerAuthContent::ContainsNone; + } + + // A simple helper function to short circuit pointer auth checks. + bool isPointerAuthenticationAvailable() const { + return LangOpts.PointerAuthCalls || LangOpts.PointerAuthIntrinsics; } private: @@ -701,15 +712,14 @@ class ASTContext : public RefCountedBase<ASTContext> { // FIXME: store in RecordDeclBitfields in future? enum class PointerAuthContent : uint8_t { - None, - AddressDiscriminatedVTable, - AddressDiscriminatedData + ContainsNone = 0, + ContainsAddressDiscriminatedVTable = 1 << 0, + ContainsAddressDiscriminatedData = 1 << 1, + ContainsDefaultAuthenticatedFunction = 1 << 2, + ContainsAllFlags = ContainsAddressDiscriminatedVTable | ContainsAddressDiscriminatedData | ContainsDefaultAuthenticatedFunction, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/ContainsDefaultAuthenticatedFunction) }; - // 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 e1dba0195f470..16434f9f9dd46 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1081,6 +1081,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 381d1fb063eba..46cfdf85e504a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1018,6 +1018,9 @@ def err_ptrauth_string_not_literal : Error< def err_ptrauth_type_disc_undiscriminated : Error< "cannot pass undiscriminated type %0 to " "'__builtin_ptrauth_type_discriminator'">; +def warn_ptrauth_weak_global_function_pointer : + Warning<"global pointer %0 uses the default pointer authentication schema">, + InGroup<PtrAuthWeakSchema>; def note_ptrauth_virtual_function_pointer_incomplete_arg_ret : Note<"cannot take an address of a virtual member function if its return or " diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index f4aadeceb4bb7..e1e6f5015cf68 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1640,23 +1640,27 @@ ASTContext::findPointerAuthContent(QualType T) const { T = T.getCanonicalType(); if (T->isDependentType()) - return PointerAuthContent::None; + return PointerAuthContent::ContainsNone; + PointerAuthContent Result = PointerAuthContent::ContainsNone; if (T.hasAddressDiscriminatedPointerAuth()) - return PointerAuthContent::AddressDiscriminatedData; + Result = Result | PointerAuthContent::ContainsAddressDiscriminatedData; + if (T->isFunctionPointerType()) { + PointerAuthQualifier ExplicitQualifier = T.getPointerAuth(); + if (!ExplicitQualifier.isPresent() || !ExplicitQualifier.isAddressDiscriminated()) + Result = Result | PointerAuthContent::ContainsDefaultAuthenticatedFunction; + } const RecordDecl *RD = T->getAsRecordDecl(); if (!RD) - return PointerAuthContent::None; + return Result; if (RD->isInvalidDecl()) - return PointerAuthContent::None; + return PointerAuthContent::ContainsNone; if (auto Existing = RecordContainsAddressDiscriminatedPointerAuth.find(RD); Existing != RecordContainsAddressDiscriminatedPointerAuth.end()) return Existing->second; - PointerAuthContent Result = PointerAuthContent::None; - auto SaveResultAndReturn = [&]() -> PointerAuthContent { auto [ResultIter, DidAdd] = RecordContainsAddressDiscriminatedPointerAuth.try_emplace(RD, Result); @@ -1665,19 +1669,16 @@ ASTContext::findPointerAuthContent(QualType T) const { assert(DidAdd); return Result; }; - auto ShouldContinueAfterUpdate = [&](PointerAuthContent NewResult) { - static_assert(PointerAuthContent::None < - PointerAuthContent::AddressDiscriminatedVTable); - static_assert(PointerAuthContent::AddressDiscriminatedVTable < - PointerAuthContent::AddressDiscriminatedData); - if (NewResult > Result) - Result = NewResult; - return Result != PointerAuthContent::AddressDiscriminatedData; + auto ShouldContinueAfterUpdate = [&](PointerAuthContent NewFlag) { + Result = Result | NewFlag; + if ((NewFlag & PointerAuthContent::ContainsAddressDiscriminatedVTable) != PointerAuthContent::ContainsNone) + Result = Result | PointerAuthContent::ContainsAddressDiscriminatedData; + return Result != PointerAuthContent::ContainsAllFlags; }; if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(RD)) { if (primaryBaseHaseAddressDiscriminatedVTableAuthentication(*this, CXXRD) && !ShouldContinueAfterUpdate( - PointerAuthContent::AddressDiscriminatedVTable)) + PointerAuthContent::ContainsAddressDiscriminatedVTable)) return SaveResultAndReturn(); for (auto Base : CXXRD->bases()) { if (!ShouldContinueAfterUpdate(findPointerAuthContent(Base.getType()))) >From d1069b81869e1c49e3dc2ea0a2fcd3ce37843f66 Mon Sep 17 00:00:00 2001 From: Oliver Hunt <[email protected]> Date: Sat, 13 Dec 2025 15:27:24 -0800 Subject: [PATCH 2/2] not to be actually merged but want to keep the tests handy --- clang/include/clang/Basic/DiagnosticGroups.td | 2 +- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/Sema.cpp | 5 +++++ clang/lib/Sema/SemaDecl.cpp | 7 +++++++ clang/test/SemaCXX/ptrauth-type-traits.cpp | 10 +++++++++- 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 16434f9f9dd46..7a9aa80a48148 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -1081,7 +1081,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">; +def PtrAuthWeakGlobalSchema : DiagGroup<"ptrauth-weak-global-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 46cfdf85e504a..c5326cf3cf717 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1019,7 +1019,7 @@ def err_ptrauth_type_disc_undiscriminated : Error< "cannot pass undiscriminated type %0 to " "'__builtin_ptrauth_type_discriminator'">; def warn_ptrauth_weak_global_function_pointer : - Warning<"global pointer %0 uses the default pointer authentication schema">, + Warning<"global variable %0 uses the default pointer authentication schema">, InGroup<PtrAuthWeakSchema>; def note_ptrauth_virtual_function_pointer_incomplete_arg_ret : diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index d32d7b960288d..dabcd1596252f 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -994,6 +994,10 @@ void Sema::getUndefinedButUsed( } } +static void checkQuestionableGlobalFunctionPointers(Sema &S) { + +} + /// checkUndefinedButUsed - Check for undefined objects with internal linkage /// or that are inline. static void checkUndefinedButUsed(Sema &S) { @@ -1624,6 +1628,7 @@ void Sema::ActOnEndOfTranslationUnit() { TUScope = nullptr; checkExposure(Context.getTranslationUnitDecl()); + checkQuestionableGlobalFunctionPointers(*this); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 47bd7295e93f6..051245630f854 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15053,6 +15053,13 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl *var) { // Build the bindings if this is a structured binding declaration. if (auto *DD = dyn_cast<DecompositionDecl>(var)) CheckCompleteDecompositionDeclaration(DD); + + if (GlobalStorage && Context.isPointerAuthenticationAvailable() && + !Diags.isIgnored(diag::warn_ptrauth_weak_global_function_pointer, var->getLocation())) { + if (Context.containsDefaultAuthenticatedFunctionPointer(var->getType())) { + Diag(var->getLocation(), diag::warn_ptrauth_weak_global_function_pointer) << var << var->getSourceRange(); + } + } } void Sema::CheckStaticLocalForDllExport(VarDecl *VD) { diff --git a/clang/test/SemaCXX/ptrauth-type-traits.cpp b/clang/test/SemaCXX/ptrauth-type-traits.cpp index a81ef1cce25b6..f4e33802e36f8 100644 --- a/clang/test/SemaCXX/ptrauth-type-traits.cpp +++ b/clang/test/SemaCXX/ptrauth-type-traits.cpp @@ -427,7 +427,15 @@ namespace GH159505 { static_assert(PTRAUTH_ENABLED != __is_trivially_copyable(Ptr<T>)); } - auto f = test<int>; + auto * __ptrauth(1,1,1) f = test<int>; + void (*__ptrauth(1,0,0) f1)() = test<int>; + void (*__ptrauth(1,1,0) f2)() = test<int>; + void (*__ptrauth(1,1,1) f3)() = test<int>; + + struct Foo { + void (*field)(); + }; + Foo object; static_assert(!__is_trivially_copyable(B<1>)); static_assert(PTRAUTH_ENABLED != __is_trivially_copyable(C<1>)); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
