Skip to content
Merged
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
11 changes: 6 additions & 5 deletions clang/docs/PointerAuthentication.rst
Original file line number Diff line number Diff line change
Expand Up @@ -284,13 +284,14 @@ __ptrauth Qualifier
^^^^^^^^^^^^^^^^^^^

``__ptrauth(key, address, discriminator)`` is an extended type
qualifier which causes so-qualified objects to hold pointers signed using the
specified schema rather than the default schema for such types.
qualifier which causes so-qualified objects to hold pointers or pointer sized
integers signed using the specified schema rather than the default schema for
such types.

In the current implementation in Clang, the qualified type must be a C pointer
type, either to a function or to an object. It currently cannot be an
Objective-C pointer type, a C++ reference type, or a block pointer type; these
restrictions may be lifted in the future.
type, either to a function or to an object, or a pointer sized integer. It
currently cannot be an Objective-C pointer type, a C++ reference type, or a
block pointer type; these restrictions may be lifted in the future.

The qualifier's operands are as follows:

Expand Down
12 changes: 10 additions & 2 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -2560,7 +2560,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); }
bool isPointerType() const;
bool isPointerOrReferenceType() const;
bool isSignableType() const;
bool isSignableType(const ASTContext &Ctx) const;
bool isSignablePointerType() const;
bool isSignableIntegerType(const ASTContext &Ctx) const;
bool isAnyPointerType() const; // Any C pointer or ObjC object pointer
bool isCountAttributedType() const;
bool isBlockPointerType() const;
Expand Down Expand Up @@ -8222,7 +8224,13 @@ inline bool Type::isAnyPointerType() const {
return isPointerType() || isObjCObjectPointerType();
}

inline bool Type::isSignableType() const { return isPointerType(); }
inline bool Type::isSignableType(const ASTContext &Ctx) const {
return isSignablePointerType() || isSignableIntegerType(Ctx);
}

inline bool Type::isSignablePointerType() const {
return isPointerType() || isObjCClassType() || isObjCQualifiedClassType();
}

inline bool Type::isBlockPointerType() const {
return isa<BlockPointerType>(CanonicalType);
Expand Down
15 changes: 9 additions & 6 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -1028,19 +1028,22 @@ def err_ptrauth_indirect_goto_addrlabel_arithmetic : Error<

// __ptrauth qualifier
def err_ptrauth_qualifier_invalid : Error<
"%select{return type|parameter type|property}1 may not be qualified with '__ptrauth'; type is %0">;
"%select{return type|parameter type|property}1 may not be qualified with "
"'__ptrauth'; type is %0">;
def err_ptrauth_qualifier_cast : Error<
"cannot cast to '__ptrauth'-qualified type %0">;
def err_ptrauth_qualifier_nonpointer : Error<
"'__ptrauth' qualifier only applies to pointer types; %0 is invalid">;
def err_ptrauth_qualifier_redundant : Error<
"type %0 is already %1-qualified">;
def err_ptrauth_qualifier_invalid_target : Error<
"'__ptrauth' qualifier only applies to pointer or pointer sized integer "
"types; %0 is invalid">;
def err_ptrauth_qualifier_redundant: Error<
"type %0 is already '__ptrauth'-qualified">;
def err_ptrauth_arg_not_ice : Error<
"argument to '__ptrauth' must be an integer constant expression">;
def err_ptrauth_address_discrimination_invalid : Error<
"invalid address discrimination flag '%0'; '__ptrauth' requires '0' or '1'">;
def err_ptrauth_extra_discriminator_invalid : Error<
"invalid extra discriminator flag '%0'; '__ptrauth' requires a value between '0' and '%1'">;
"invalid extra discriminator flag '%0'; '__ptrauth' requires a value between "
"'0' and '%1'">;

/// main()
// static main() is not an error in C, just in C++.
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2943,6 +2943,9 @@ bool ASTContext::hasUniqueObjectRepresentations(

// All integrals and enums are unique.
if (Ty->isIntegralOrEnumerationType()) {
// Address discriminated integer types are not unique.
if (Ty.hasAddressDiscriminatedPointerAuth())
return false;
// Except _BitInt types that have padding bits.
if (const auto *BIT = Ty->getAs<BitIntType>())
return getTypeSize(BIT) == BIT->getNumBits();
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5062,6 +5062,12 @@ AttributedType::stripOuterNullability(QualType &T) {
return std::nullopt;
}

bool Type::isSignableIntegerType(const ASTContext &Ctx) const {
if (!isIntegralType(Ctx) || isEnumeralType())
return false;
return Ctx.getTypeSize(this) == Ctx.getTypeSize(Ctx.VoidPtrTy);
}

bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
const auto *objcPtr = getAs<ObjCObjectPointerType>();
if (!objcPtr)
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/CodeGen/CGExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2444,6 +2444,10 @@ ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
EnablePtrAuthFunctionTypeDiscrimination)
.tryEmit();
case APValue::Int:
if (PointerAuthQualifier PointerAuth = DestType.getPointerAuth();
PointerAuth &&
(PointerAuth.authenticatesNullValues() || Value.getInt() != 0))
return nullptr;
return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt());
case APValue::FixedPoint:
return llvm::ConstantInt::get(CGM.getLLVMContext(),
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2300,7 +2300,7 @@ static bool isLValueKnownNonNull(CodeGenFunction &CGF, const Expr *E) {
}

bool CodeGenFunction::isPointerKnownNonNull(const Expr *E) {
assert(E->getType()->isSignableType());
assert(E->getType()->isSignableType(getContext()));

E = E->IgnoreParens();

Expand Down
17 changes: 10 additions & 7 deletions clang/lib/CodeGen/CGPointerAuth.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) {
/// pointer type.
static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM,
QualType PointerType) {
assert(PointerType->isSignableType());
assert(PointerType->isSignableType(CGM.getContext()));

// Block pointers are currently not signed.
if (PointerType->isBlockPointerType())
Expand Down Expand Up @@ -209,7 +209,7 @@ emitLoadOfOrigPointerRValue(CodeGenFunction &CGF, const LValue &LV,
/// needlessly resigning the pointer.
std::pair<llvm::Value *, CGPointerAuthInfo>
CodeGenFunction::EmitOrigPointerRValue(const Expr *E) {
assert(E->getType()->isSignableType());
assert(E->getType()->isSignableType(getContext()));

E = E->IgnoreParens();
if (const auto *Load = dyn_cast<ImplicitCastExpr>(E)) {
Expand Down Expand Up @@ -291,7 +291,10 @@ static bool equalAuthPolicies(const CGPointerAuthInfo &Left,
if (Left.isSigned() != Right.isSigned())
return false;
return Left.getKey() == Right.getKey() &&
Left.getAuthenticationMode() == Right.getAuthenticationMode();
Left.getAuthenticationMode() == Right.getAuthenticationMode() &&
Left.isIsaPointer() == Right.isIsaPointer() &&
Left.authenticatesNullValues() == Right.authenticatesNullValues() &&
Left.getDiscriminator() == Right.getDiscriminator();
}

// Return the discriminator or return zero if the discriminator is null.
Expand Down Expand Up @@ -642,10 +645,10 @@ llvm::Value *CodeGenFunction::authPointerToPointerCast(llvm::Value *ResultPtr,
QualType SourceType,
QualType DestType) {
CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
if (SourceType->isSignableType())
if (SourceType->isSignableType(getContext()))
CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);

if (DestType->isSignableType())
if (DestType->isSignableType(getContext()))
NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);

if (!CurAuthInfo && !NewAuthInfo)
Expand All @@ -667,10 +670,10 @@ Address CodeGenFunction::authPointerToPointerCast(Address Ptr,
QualType SourceType,
QualType DestType) {
CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
if (SourceType->isSignableType())
if (SourceType->isSignableType(getContext()))
CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);

if (DestType->isSignableType())
if (DestType->isSignableType(getContext()))
NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);

if (!CurAuthInfo && !NewAuthInfo)
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10888,7 +10888,7 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
return;
}

// Ill-formed if the field is an address-discriminated pointer.
// Ill-formed if the field is an address-discriminated value.
if (FT.hasAddressDiscriminatedPointerAuth()) {
PrintDiagAndRemoveAttr(6);
return;
Expand Down
10 changes: 5 additions & 5 deletions clang/lib/Sema/SemaType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8379,15 +8379,14 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
return;
}

if (!T->isSignableType() && !T->isDependentType()) {
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_nonpointer) << T;
if (!T->isSignableType(Ctx) && !T->isDependentType()) {
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_invalid_target) << T;
Attr.setInvalid();
return;
}

if (T.getPointerAuth()) {
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_redundant)
<< T << Attr.getAttrName()->getName();
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_redundant) << T;
Attr.setInvalid();
return;
}
Expand All @@ -8402,7 +8401,8 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
"address discriminator arg should be either 0 or 1");
PointerAuthQualifier Qual = PointerAuthQualifier::Create(
Key, IsAddressDiscriminated, ExtraDiscriminator,
PointerAuthenticationMode::SignAndAuth, false, false);
PointerAuthenticationMode::SignAndAuth, /*IsIsaPointer=*/false,
/*AuthenticatesNullValues=*/false);
T = S.Context.getPointerAuthType(T, Qual);
}

Expand Down
12 changes: 7 additions & 5 deletions clang/lib/Sema/TreeTransform.h
Original file line number Diff line number Diff line change
Expand Up @@ -5305,13 +5305,15 @@ QualType TreeTransform<Derived>::RebuildQualifiedType(QualType T,
PointerAuthQualifier LocalPointerAuth = Quals.getPointerAuth();
if (LocalPointerAuth.isPresent()) {
if (T.getPointerAuth().isPresent()) {
SemaRef.Diag(Loc, diag::err_ptrauth_qualifier_redundant)
<< TL.getType() << "__ptrauth";
return QualType();
} else if (!T->isSignableType() && !T->isDependentType()) {
SemaRef.Diag(Loc, diag::err_ptrauth_qualifier_nonpointer) << T;
SemaRef.Diag(Loc, diag::err_ptrauth_qualifier_redundant) << TL.getType();
return QualType();
}
if (!T->isDependentType()) {
if (!T->isSignableType(SemaRef.getASTContext())) {
SemaRef.Diag(Loc, diag::err_ptrauth_qualifier_invalid_target) << T;
return QualType();
}
}
}
// C++ [dcl.fct]p7:
// [When] adding cv-qualifications on top of the function type [...] the
Expand Down
Loading