Skip to content

Commit 07b6275

Browse files
committed
[clang] Add support for __ptrauth being applied to integer types
This adds support for the __ptrauth qualifier to be applied to pointer sized integer types.
1 parent c16297c commit 07b6275

File tree

14 files changed

+329
-33
lines changed

14 files changed

+329
-33
lines changed

clang/docs/PointerAuthentication.rst

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -284,13 +284,14 @@ __ptrauth Qualifier
284284
^^^^^^^^^^^^^^^^^^^
285285

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

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

295296
The qualifier's operands are as follows:
296297

clang/include/clang/AST/Type.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2560,7 +2560,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
25602560
bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); }
25612561
bool isPointerType() const;
25622562
bool isPointerOrReferenceType() const;
2563-
bool isSignableType() const;
2563+
bool isSignableType(const ASTContext &Ctx) const;
2564+
bool isSignablePointerType() const;
2565+
bool isSignableIntegerType(const ASTContext &Ctx) const;
25642566
bool isAnyPointerType() const; // Any C pointer or ObjC object pointer
25652567
bool isCountAttributedType() const;
25662568
bool isBlockPointerType() const;
@@ -8222,7 +8224,13 @@ inline bool Type::isAnyPointerType() const {
82228224
return isPointerType() || isObjCObjectPointerType();
82238225
}
82248226

8225-
inline bool Type::isSignableType() const { return isPointerType(); }
8227+
inline bool Type::isSignableType(const ASTContext &Ctx) const {
8228+
return isSignablePointerType() || isSignableIntegerType(Ctx);
8229+
}
8230+
8231+
inline bool Type::isSignablePointerType() const {
8232+
return isPointerType() || isObjCClassType() || isObjCQualifiedClassType();
8233+
}
82268234

82278235
inline bool Type::isBlockPointerType() const {
82288236
return isa<BlockPointerType>(CanonicalType);

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,10 +1031,12 @@ def err_ptrauth_qualifier_invalid : Error<
10311031
"%select{return type|parameter type|property}1 may not be qualified with '__ptrauth'; type is %0">;
10321032
def err_ptrauth_qualifier_cast : Error<
10331033
"cannot cast to '__ptrauth'-qualified type %0">;
1034-
def err_ptrauth_qualifier_nonpointer : Error<
1035-
"'__ptrauth' qualifier only applies to pointer types; %0 is invalid">;
1036-
def err_ptrauth_qualifier_redundant : Error<
1037-
"type %0 is already %1-qualified">;
1034+
def err_ptrauth_qualifier_invalid_target
1035+
: Error<"'__ptrauth' qualifier only applies to pointer or pointer sized "
1036+
"integer"
1037+
" types; %0 is invalid">;
1038+
def err_ptrauth_qualifier_redundant
1039+
: Error<"type %0 is already __ptrauth-qualified">;
10381040
def err_ptrauth_arg_not_ice : Error<
10391041
"argument to '__ptrauth' must be an integer constant expression">;
10401042
def err_ptrauth_address_discrimination_invalid : Error<

clang/lib/AST/ASTContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2943,6 +2943,9 @@ bool ASTContext::hasUniqueObjectRepresentations(
29432943

29442944
// All integrals and enums are unique.
29452945
if (Ty->isIntegralOrEnumerationType()) {
2946+
// Address discriminated integer types are not unique.
2947+
if (Ty.hasAddressDiscriminatedPointerAuth())
2948+
return false;
29462949
// Except _BitInt types that have padding bits.
29472950
if (const auto *BIT = Ty->getAs<BitIntType>())
29482951
return getTypeSize(BIT) == BIT->getNumBits();

clang/lib/AST/Type.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5062,6 +5062,12 @@ AttributedType::stripOuterNullability(QualType &T) {
50625062
return std::nullopt;
50635063
}
50645064

5065+
bool Type::isSignableIntegerType(const ASTContext &Ctx) const {
5066+
if (!isIntegralType(Ctx) || isEnumeralType())
5067+
return false;
5068+
return Ctx.getTypeSize(this) == Ctx.getTypeSize(Ctx.VoidPtrTy);
5069+
}
5070+
50655071
bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
50665072
const auto *objcPtr = getAs<ObjCObjectPointerType>();
50675073
if (!objcPtr)

clang/lib/CodeGen/CGExprConstant.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,6 +2444,10 @@ ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
24442444
EnablePtrAuthFunctionTypeDiscrimination)
24452445
.tryEmit();
24462446
case APValue::Int:
2447+
if (PointerAuthQualifier PointerAuth = DestType.getPointerAuth();
2448+
PointerAuth &&
2449+
(PointerAuth.authenticatesNullValues() || Value.getInt() != 0))
2450+
return nullptr;
24472451
return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt());
24482452
case APValue::FixedPoint:
24492453
return llvm::ConstantInt::get(CGM.getLLVMContext(),

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2300,7 +2300,7 @@ static bool isLValueKnownNonNull(CodeGenFunction &CGF, const Expr *E) {
23002300
}
23012301

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

23052305
E = E->IgnoreParens();
23062306

clang/lib/CodeGen/CGPointerAuth.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ CGPointerAuthInfo CodeGenModule::getPointerAuthInfoForPointeeType(QualType T) {
175175
/// pointer type.
176176
static CGPointerAuthInfo getPointerAuthInfoForType(CodeGenModule &CGM,
177177
QualType PointerType) {
178-
assert(PointerType->isSignableType());
178+
assert(PointerType->isSignableType(CGM.getContext()));
179179

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

214214
E = E->IgnoreParens();
215215
if (const auto *Load = dyn_cast<ImplicitCastExpr>(E)) {
@@ -291,7 +291,10 @@ static bool equalAuthPolicies(const CGPointerAuthInfo &Left,
291291
if (Left.isSigned() != Right.isSigned())
292292
return false;
293293
return Left.getKey() == Right.getKey() &&
294-
Left.getAuthenticationMode() == Right.getAuthenticationMode();
294+
Left.getAuthenticationMode() == Right.getAuthenticationMode() &&
295+
Left.isIsaPointer() == Right.isIsaPointer() &&
296+
Left.authenticatesNullValues() == Right.authenticatesNullValues() &&
297+
Left.getDiscriminator() == Right.getDiscriminator();
295298
}
296299

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

648-
if (DestType->isSignableType())
651+
if (DestType->isSignableType(getContext()))
649652
NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
650653

651654
if (!CurAuthInfo && !NewAuthInfo)
@@ -667,10 +670,10 @@ Address CodeGenFunction::authPointerToPointerCast(Address Ptr,
667670
QualType SourceType,
668671
QualType DestType) {
669672
CGPointerAuthInfo CurAuthInfo, NewAuthInfo;
670-
if (SourceType->isSignableType())
673+
if (SourceType->isSignableType(getContext()))
671674
CurAuthInfo = getPointerAuthInfoForType(CGM, SourceType);
672675

673-
if (DestType->isSignableType())
676+
if (DestType->isSignableType(getContext()))
674677
NewAuthInfo = getPointerAuthInfoForType(CGM, DestType);
675678

676679
if (!CurAuthInfo && !NewAuthInfo)

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10888,7 +10888,7 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) {
1088810888
return;
1088910889
}
1089010890

10891-
// Ill-formed if the field is an address-discriminated pointer.
10891+
// Ill-formed if the field is an address-discriminated value.
1089210892
if (FT.hasAddressDiscriminatedPointerAuth()) {
1089310893
PrintDiagAndRemoveAttr(6);
1089410894
return;

clang/lib/Sema/SemaType.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8379,15 +8379,14 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
83798379
return;
83808380
}
83818381

8382-
if (!T->isSignableType() && !T->isDependentType()) {
8383-
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_nonpointer) << T;
8382+
if (!T->isSignableType(Ctx) && !T->isDependentType()) {
8383+
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_invalid_target) << T;
83848384
Attr.setInvalid();
83858385
return;
83868386
}
83878387

83888388
if (T.getPointerAuth()) {
8389-
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_redundant)
8390-
<< T << Attr.getAttrName()->getName();
8389+
S.Diag(Attr.getLoc(), diag::err_ptrauth_qualifier_redundant) << T;
83918390
Attr.setInvalid();
83928391
return;
83938392
}
@@ -8402,7 +8401,8 @@ static void HandlePtrAuthQualifier(ASTContext &Ctx, QualType &T,
84028401
"address discriminator arg should be either 0 or 1");
84038402
PointerAuthQualifier Qual = PointerAuthQualifier::Create(
84048403
Key, IsAddressDiscriminated, ExtraDiscriminator,
8405-
PointerAuthenticationMode::SignAndAuth, false, false);
8404+
PointerAuthenticationMode::SignAndAuth, /*IsIsaPointer=*/false,
8405+
/*AuthenticatesNullValues=*/false);
84068406
T = S.Context.getPointerAuthType(T, Qual);
84078407
}
84088408

0 commit comments

Comments
 (0)