Skip to content

Commit 98ea512

Browse files
authored
[clang][bytecode] Clear inactive union fields when copying (#134982)
When copying unions, we need to only copy the active field of the source union, which we were already doing. However, we also need to zero out the (now) inactive fields, so we don't end up with dangling pointers in those inactive fields.
1 parent 2828328 commit 98ea512

File tree

2 files changed

+570
-1
lines changed

2 files changed

+570
-1
lines changed

clang/lib/AST/ByteCode/InterpBuiltin.cpp

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2723,6 +2723,45 @@ bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
27232723
return true;
27242724
}
27252725

2726+
static void zeroAll(Pointer &Dest) {
2727+
const Descriptor *Desc = Dest.getFieldDesc();
2728+
2729+
if (Desc->isPrimitive()) {
2730+
TYPE_SWITCH(Desc->getPrimType(), {
2731+
Dest.deref<T>().~T();
2732+
new (&Dest.deref<T>()) T();
2733+
});
2734+
return;
2735+
}
2736+
2737+
if (Desc->isRecord()) {
2738+
const Record *R = Desc->ElemRecord;
2739+
for (const Record::Field &F : R->fields()) {
2740+
Pointer FieldPtr = Dest.atField(F.Offset);
2741+
zeroAll(FieldPtr);
2742+
}
2743+
return;
2744+
}
2745+
2746+
if (Desc->isPrimitiveArray()) {
2747+
for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
2748+
TYPE_SWITCH(Desc->getPrimType(), {
2749+
Dest.deref<T>().~T();
2750+
new (&Dest.deref<T>()) T();
2751+
});
2752+
}
2753+
return;
2754+
}
2755+
2756+
if (Desc->isCompositeArray()) {
2757+
for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
2758+
Pointer ElemPtr = Dest.atIndex(I).narrow();
2759+
zeroAll(ElemPtr);
2760+
}
2761+
return;
2762+
}
2763+
}
2764+
27262765
static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
27272766
Pointer &Dest, bool Activate);
27282767
static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
@@ -2751,11 +2790,14 @@ static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
27512790
const Record *R = DestDesc->ElemRecord;
27522791
for (const Record::Field &F : R->fields()) {
27532792
if (R->isUnion()) {
2754-
// For unions, only copy the active field.
2793+
// For unions, only copy the active field. Zero all others.
27552794
const Pointer &SrcField = Src.atField(F.Offset);
27562795
if (SrcField.isActive()) {
27572796
if (!copyField(F, /*Activate=*/true))
27582797
return false;
2798+
} else {
2799+
Pointer DestField = Dest.atField(F.Offset);
2800+
zeroAll(DestField);
27592801
}
27602802
} else {
27612803
if (!copyField(F, Activate))

0 commit comments

Comments
 (0)