Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 19 additions & 9 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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:
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/DiagnosticGroups.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 PtrAuthWeakGlobalSchema : DiagGroup<"ptrauth-weak-global-schema">;

// This covers both the deprecated case (in C++98)
// and the extension case (in C++11 onwards).
Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 variable %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 "
Expand Down
31 changes: 16 additions & 15 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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())))
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/Sema/Sema.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -1624,6 +1628,7 @@ void Sema::ActOnEndOfTranslationUnit() {
TUScope = nullptr;

checkExposure(Context.getTranslationUnitDecl());
checkQuestionableGlobalFunctionPointers(*this);
}


Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
10 changes: 9 additions & 1 deletion clang/test/SemaCXX/ptrauth-type-traits.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>));

Expand Down
Loading