Skip to content

Commit 7c8c531

Browse files
committed
[clang][ptrauth] Ensure correct copying of records with authenticated fields
1 parent afda4c2 commit 7c8c531

File tree

13 files changed

+421
-2
lines changed

13 files changed

+421
-2
lines changed

clang/include/clang/AST/NonTrivialTypeVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ struct CopiedTypeVisitor {
9595
return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...);
9696
case QualType::PCK_Struct:
9797
return asDerived().visitStruct(FT, std::forward<Ts>(Args)...);
98+
case QualType::PCK_PtrAuth:
99+
return asDerived().visitPtrAuth(FT, std::forward<Ts>(Args)...);
98100
case QualType::PCK_Trivial:
99101
return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...);
100102
case QualType::PCK_VolatileTrivial:

clang/include/clang/AST/Type.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,9 @@ class QualType {
15071507
/// with the ARC __weak qualifier.
15081508
PCK_ARCWeak,
15091509

1510+
/// The type is an address-discriminated signed pointer type.
1511+
PCK_PtrAuth,
1512+
15101513
/// The type is a struct containing a field whose type is neither
15111514
/// PCK_Trivial nor PCK_VolatileTrivial.
15121515
/// Note that a C++ struct type does not necessarily match this; C++ copying

clang/lib/AST/ASTContext.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8372,6 +8372,9 @@ bool ASTContext::BlockRequiresCopying(QualType Ty,
83728372
return true;
83738373
}
83748374

8375+
if (Ty.hasAddressDiscriminatedPointerAuth())
8376+
return true;
8377+
83758378
// The block needs copy/destroy helpers if Ty is non-trivial to destructively
83768379
// move or destroy.
83778380
if (Ty.isNonTrivialToPrimitiveDestructiveMove() || Ty.isDestructedType())

clang/lib/AST/Type.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2801,6 +2801,10 @@ static bool isTriviallyCopyableTypeImpl(const QualType &type,
28012801
if (type.hasNonTrivialObjCLifetime())
28022802
return false;
28032803

2804+
QualType::PrimitiveCopyKind PCK = type.isNonTrivialToPrimitiveCopy();
2805+
if (PCK != QualType::PCK_Trivial && PCK != QualType::PCK_VolatileTrivial)
2806+
return false;
2807+
28042808
// C++11 [basic.types]p9 - See Core 2094
28052809
// Scalar types, trivially copyable class types, arrays of such types, and
28062810
// cv-qualified versions of these types are collectively
@@ -2968,6 +2972,8 @@ QualType::PrimitiveCopyKind QualType::isNonTrivialToPrimitiveCopy() const {
29682972
case Qualifiers::OCL_Weak:
29692973
return PCK_ARCWeak;
29702974
default:
2975+
if (hasAddressDiscriminatedPointerAuth())
2976+
return PCK_PtrAuth;
29712977
return Qs.hasVolatile() ? PCK_VolatileTrivial : PCK_Trivial;
29722978
}
29732979
}

clang/lib/CodeGen/CGBlocks.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1591,6 +1591,10 @@ computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
15911591
return std::make_pair(BlockCaptureEntityKind::BlockObject, Flags);
15921592
}
15931593

1594+
if (T.hasAddressDiscriminatedPointerAuth())
1595+
return std::make_pair(
1596+
BlockCaptureEntityKind::AddressDiscriminatedPointerAuth, Flags);
1597+
15941598
Flags = BLOCK_FIELD_IS_OBJECT;
15951599
bool isBlockPointer = T->isBlockPointerType();
15961600
if (isBlockPointer)
@@ -1611,6 +1615,10 @@ computeCopyInfoForBlockCapture(const BlockDecl::Capture &CI, QualType T,
16111615
return std::make_pair(!isBlockPointer ? BlockCaptureEntityKind::ARCStrong
16121616
: BlockCaptureEntityKind::BlockObject,
16131617
Flags);
1618+
case QualType::PCK_PtrAuth:
1619+
return std::make_pair(
1620+
BlockCaptureEntityKind::AddressDiscriminatedPointerAuth,
1621+
BlockFieldFlags());
16141622
case QualType::PCK_Trivial:
16151623
case QualType::PCK_VolatileTrivial: {
16161624
if (!T->isObjCRetainableType())
@@ -1713,6 +1721,13 @@ static std::string getBlockCaptureStr(const CGBlockInfo::Capture &Cap,
17131721
case BlockCaptureEntityKind::ARCStrong:
17141722
Str += "s";
17151723
break;
1724+
case BlockCaptureEntityKind::AddressDiscriminatedPointerAuth: {
1725+
auto PtrAuth = CaptureTy.getPointerAuth();
1726+
assert(PtrAuth && PtrAuth.isAddressDiscriminated());
1727+
Str += "p" + llvm::to_string(PtrAuth.getKey()) + "d" +
1728+
llvm::to_string(PtrAuth.getExtraDiscriminator());
1729+
break;
1730+
}
17161731
case BlockCaptureEntityKind::BlockObject: {
17171732
const VarDecl *Var = CI.getVariable();
17181733
unsigned F = Flags.getBitMask();
@@ -1829,6 +1844,7 @@ static void pushCaptureCleanup(BlockCaptureEntityKind CaptureKind,
18291844
}
18301845
break;
18311846
}
1847+
case BlockCaptureEntityKind::AddressDiscriminatedPointerAuth:
18321848
case BlockCaptureEntityKind::None:
18331849
break;
18341850
}
@@ -1925,6 +1941,14 @@ CodeGenFunction::GenerateCopyHelperFunction(const CGBlockInfo &blockInfo) {
19251941
case BlockCaptureEntityKind::ARCWeak:
19261942
EmitARCCopyWeak(dstField, srcField);
19271943
break;
1944+
case BlockCaptureEntityKind::AddressDiscriminatedPointerAuth: {
1945+
QualType Type = CI.getVariable()->getType();
1946+
PointerAuthQualifier PointerAuth = Type.getPointerAuth();
1947+
assert(PointerAuth && PointerAuth.isAddressDiscriminated());
1948+
EmitPointerAuthCopy(PointerAuth, Type, dstField, srcField);
1949+
// We don't need to push cleanups for ptrauth types.
1950+
continue;
1951+
}
19281952
case BlockCaptureEntityKind::NonTrivialCStruct: {
19291953
// If this is a C struct that requires non-trivial copy construction,
19301954
// emit a call to its copy constructor.
@@ -2261,6 +2285,33 @@ class CXXByrefHelpers final : public BlockByrefHelpers {
22612285
}
22622286
};
22632287

2288+
/// Emits the copy/dispose helpers for a __block variable with
2289+
/// address-discriminated pointer authentication.
2290+
class AddressDiscriminatedByrefHelpers final : public BlockByrefHelpers {
2291+
QualType VarType;
2292+
2293+
public:
2294+
AddressDiscriminatedByrefHelpers(CharUnits Alignment, QualType Type)
2295+
: BlockByrefHelpers(Alignment), VarType(Type) {
2296+
assert(Type.hasAddressDiscriminatedPointerAuth());
2297+
}
2298+
2299+
void emitCopy(CodeGenFunction &CGF, Address DestField,
2300+
Address SrcField) override {
2301+
CGF.EmitPointerAuthCopy(VarType.getPointerAuth(), VarType, DestField,
2302+
SrcField);
2303+
}
2304+
2305+
bool needsDispose() const override { return false; }
2306+
void emitDispose(CodeGenFunction &CGF, Address Field) override {
2307+
llvm_unreachable("should never be called");
2308+
}
2309+
2310+
void profileImpl(llvm::FoldingSetNodeID &ID) const override {
2311+
ID.AddPointer(VarType.getCanonicalType().getAsOpaquePtr());
2312+
}
2313+
};
2314+
22642315
/// Emits the copy/dispose helpers for a __block variable that is a non-trivial
22652316
/// C struct.
22662317
class NonTrivialCStructByrefHelpers final : public BlockByrefHelpers {
@@ -2462,7 +2513,10 @@ CodeGenFunction::buildByrefHelpers(llvm::StructType &byrefType,
24622513
return ::buildByrefHelpers(
24632514
CGM, byrefInfo, CXXByrefHelpers(valueAlignment, type, copyExpr));
24642515
}
2465-
2516+
if (type.hasAddressDiscriminatedPointerAuth()) {
2517+
return ::buildByrefHelpers(
2518+
CGM, byrefInfo, AddressDiscriminatedByrefHelpers(valueAlignment, type));
2519+
}
24662520
// If type is a non-trivial C struct type that is non-trivial to
24672521
// destructly move or destroy, build the copy and dispose helpers.
24682522
if (type.isNonTrivialToPrimitiveDestructiveMove() == QualType::PCK_Struct ||

clang/lib/CodeGen/CGBlocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ class BlockByrefInfo {
146146
enum class BlockCaptureEntityKind {
147147
None,
148148
CXXRecord, // Copy or destroy
149+
AddressDiscriminatedPointerAuth,
149150
ARCWeak,
150151
ARCStrong,
151152
NonTrivialCStruct,

clang/lib/CodeGen/CGCall.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4857,7 +4857,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E,
48574857

48584858
if (HasAggregateEvalKind && isa<ImplicitCastExpr>(E) &&
48594859
cast<CastExpr>(E)->getCastKind() == CK_LValueToRValue &&
4860-
!type->isArrayParameterType()) {
4860+
!type->isArrayParameterType() && !type.isNonTrivialToPrimitiveCopy()) {
48614861
LValue L = EmitLValue(cast<CastExpr>(E)->getSubExpr());
48624862
assert(L.isSimple());
48634863
args.addUncopiedAggregate(L, type);

clang/lib/CodeGen/CGNonTrivialStruct.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,18 @@ struct GenBinaryFuncName : CopyStructVisitor<GenBinaryFuncName<IsMove>, IsMove>,
266266
this->appendStr("_tv" + llvm::to_string(OffsetInBits) + "w" +
267267
llvm::to_string(getFieldSize(FD, FT, this->Ctx)));
268268
}
269+
270+
void visitPtrAuth(QualType FT, const FieldDecl *FD,
271+
CharUnits CurStructOffset) {
272+
this->appendStr("_pa");
273+
PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
274+
this->appendStr(llvm::to_string(PtrAuth.getKey()) + "_");
275+
this->appendStr(llvm::to_string(PtrAuth.getExtraDiscriminator()) + "_");
276+
if (PtrAuth.authenticatesNullValues())
277+
this->appendStr("anv_");
278+
CharUnits FieldOffset = CurStructOffset + this->getFieldOffset(FD);
279+
this->appendStr(llvm::to_string(FieldOffset.getQuantity()));
280+
}
269281
};
270282

271283
struct GenDefaultInitializeFuncName
@@ -568,6 +580,13 @@ struct GenBinaryFunc : CopyStructVisitor<Derived, IsMove>,
568580
RValue SrcVal = this->CGF->EmitLoadOfLValue(SrcLV, SourceLocation());
569581
this->CGF->EmitStoreThroughLValue(SrcVal, DstLV);
570582
}
583+
void visitPtrAuth(QualType FT, const FieldDecl *FD, CharUnits CurStackOffset,
584+
std::array<Address, 2> Addrs) {
585+
PointerAuthQualifier PtrAuth = FT.getPointerAuth().withoutKeyNone();
586+
Addrs[DstIdx] = this->getAddrWithOffset(Addrs[DstIdx], CurStackOffset, FD);
587+
Addrs[SrcIdx] = this->getAddrWithOffset(Addrs[SrcIdx], CurStackOffset, FD);
588+
this->CGF->EmitPointerAuthCopy(PtrAuth, FT, Addrs[DstIdx], Addrs[SrcIdx]);
589+
}
571590
};
572591

573592
// These classes that emit the special functions for a non-trivial struct.

clang/lib/Sema/SemaChecking.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9443,6 +9443,9 @@ struct SearchNonTrivialToCopyField
94439443
void visitARCWeak(QualType FT, SourceLocation SL) {
94449444
S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
94459445
}
9446+
void visitPtrAuth(QualType FT, SourceLocation SL) {
9447+
S.DiagRuntimeBehavior(SL, E, S.PDiag(diag::note_nontrivial_field) << 0);
9448+
}
94469449
void visitStruct(QualType FT, SourceLocation SL) {
94479450
for (const FieldDecl *FD : FT->castAs<RecordType>()->getDecl()->fields())
94489451
visit(FD->getType(), FD->getLocation());

clang/lib/Sema/SemaDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13395,6 +13395,12 @@ struct DiagNonTrivalCUnionCopyVisitor
1339513395
asDerived().visit(FD->getType(), FD, InNonTrivialUnion);
1339613396
}
1339713397

13398+
void visitPtrAuth(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {
13399+
if (InNonTrivialUnion)
13400+
S.Diag(FD->getLocation(), diag::note_non_trivial_c_union)
13401+
<< 1 << 2 << QT << FD->getName();
13402+
}
13403+
1339813404
void preVisit(QualType::PrimitiveCopyKind PCK, QualType QT,
1339913405
const FieldDecl *FD, bool InNonTrivialUnion) {}
1340013406
void visitTrivial(QualType QT, const FieldDecl *FD, bool InNonTrivialUnion) {}

0 commit comments

Comments
 (0)