Skip to content

Commit 65a6cbd

Browse files
authored
[clang] Add support for __ptrauth being applied to integer types (#137580)
Allows the __ptrauth qualifier to be applied to pointer sized integer types, updates Sema to ensure trivially copyable, etc correctly handle address discriminated integers, and updates codegen to perform authentication around arithmetic on the types.
1 parent 73ca116 commit 65a6cbd

15 files changed

+334
-37
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;
@@ -8216,7 +8218,13 @@ inline bool Type::isAnyPointerType() const {
82168218
return isPointerType() || isObjCObjectPointerType();
82178219
}
82188220

8219-
inline bool Type::isSignableType() const { return isPointerType(); }
8221+
inline bool Type::isSignableType(const ASTContext &Ctx) const {
8222+
return isSignablePointerType() || isSignableIntegerType(Ctx);
8223+
}
8224+
8225+
inline bool Type::isSignablePointerType() const {
8226+
return isPointerType() || isObjCClassType() || isObjCQualifiedClassType();
8227+
}
82208228

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

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,19 +1028,22 @@ def err_ptrauth_indirect_goto_addrlabel_arithmetic : Error<
10281028

10291029
// __ptrauth qualifier
10301030
def err_ptrauth_qualifier_invalid : Error<
1031-
"%select{return type|parameter type|property}1 may not be qualified with '__ptrauth'; type is %0">;
1031+
"%select{return type|parameter type|property}1 may not be qualified with "
1032+
"'__ptrauth'; type is %0">;
10321033
def err_ptrauth_qualifier_cast : Error<
10331034
"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">;
1035+
def err_ptrauth_qualifier_invalid_target : Error<
1036+
"'__ptrauth' qualifier only applies to pointer or pointer sized integer "
1037+
"types; %0 is invalid">;
1038+
def err_ptrauth_qualifier_redundant: Error<
1039+
"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<
10411043
"invalid address discrimination flag '%0'; '__ptrauth' requires '0' or '1'">;
10421044
def err_ptrauth_extra_discriminator_invalid : Error<
1043-
"invalid extra discriminator flag '%0'; '__ptrauth' requires a value between '0' and '%1'">;
1045+
"invalid extra discriminator flag '%0'; '__ptrauth' requires a value between "
1046+
"'0' and '%1'">;
10441047

10451048
/// main()
10461049
// static main() is not an error in C, just in C++.

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
@@ -5075,6 +5075,12 @@ AttributedType::stripOuterNullability(QualType &T) {
50755075
return std::nullopt;
50765076
}
50775077

5078+
bool Type::isSignableIntegerType(const ASTContext &Ctx) const {
5079+
if (!isIntegralType(Ctx) || isEnumeralType())
5080+
return false;
5081+
return Ctx.getTypeSize(this) == Ctx.getTypeSize(Ctx.VoidPtrTy);
5082+
}
5083+
50785084
bool Type::isBlockCompatibleObjCPointerType(ASTContext &ctx) const {
50795085
const auto *objcPtr = getAs<ObjCObjectPointerType>();
50805086
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)