Skip to content

Commit 8fe4c77

Browse files
committed
[Runtime] Properly mask pointers before ref counting and other fixes
The fixes are all around enum support. Some tag comparisons and pointer masking were incorrect and led to crashes. rdar://114575149
1 parent 2006c64 commit 8fe4c77

File tree

1 file changed

+65
-36
lines changed

1 file changed

+65
-36
lines changed

stdlib/public/runtime/BytecodeLayouts.cpp

Lines changed: 65 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -662,7 +662,8 @@ static void objcStrongDestroyBranchless(const Metadata *metadata,
662662
LayoutStringReader1 &reader,
663663
uintptr_t &addrOffset,
664664
uint8_t *addr) {
665-
objc_object *object = (objc_object*)(*(uintptr_t *)(addr + addrOffset));
665+
objc_object *object = (objc_object *)((*(uintptr_t *)(addr + addrOffset)) &
666+
~_swift_abi_SwiftSpareBitsMask);
666667
addrOffset += sizeof(objc_object*);
667668
objc_release(object);
668669
}
@@ -697,7 +698,9 @@ static void resilientDestroyBranchless(const Metadata *metadata,
697698
uintptr_t &addrOffset,
698699
uint8_t *addr) {
699700
auto *type = getResilientTypeMetadata(metadata, reader);
700-
type->vw_destroy((OpaqueValue *)(addr + addrOffset));
701+
auto *object = (OpaqueValue *)(addr + addrOffset);
702+
addrOffset += type->vw_size();
703+
type->vw_destroy(object);
701704
}
702705

703706
typedef void (*DestrFnBranchless)(const Metadata *metadata,
@@ -891,10 +894,11 @@ static void objcStrongRetainBranchless(const Metadata *metadata,
891894
uint8_t *dest,
892895
uint8_t *src) {
893896
uintptr_t _addrOffset = addrOffset;
894-
objc_object *object = (objc_object*)(*(uintptr_t *)(src + _addrOffset));
895-
memcpy(dest + _addrOffset, &object, sizeof(objc_object*));
896-
addrOffset = _addrOffset + sizeof(objc_object*);
897-
objc_retain(object);
897+
uintptr_t object = *(uintptr_t *)(src + _addrOffset);
898+
memcpy(dest + _addrOffset, &object, sizeof(objc_object *));
899+
object &= ~_swift_abi_SwiftSpareBitsMask;
900+
addrOffset = _addrOffset + sizeof(objc_object *);
901+
objc_retain((objc_object *)object);
898902
}
899903
#endif
900904

@@ -1004,6 +1008,8 @@ swift_generic_initWithCopy(swift::OpaqueValue *dest, swift::OpaqueValue *src,
10041008
uintptr_t addrOffset = 0;
10051009
handleRefCountsInitWithCopy(metadata, reader, addrOffset, (uint8_t *)dest, (uint8_t *)src);
10061010

1011+
assert(addrOffset == metadata->vw_size());
1012+
10071013
return dest;
10081014
}
10091015

@@ -1062,8 +1068,10 @@ static void existentialInitWithTake(const Metadata *metadata,
10621068
auto *destObject = (OpaqueValue *)(dest + _addrOffset);
10631069
auto *srcObject = (OpaqueValue *)(src + _addrOffset);
10641070
addrOffset = _addrOffset + (sizeof(uintptr_t) * NumWords_ValueBuffer);
1065-
if (SWIFT_UNLIKELY(!type->getValueWitnesses()->isBitwiseTakable())) {
1071+
if (type->getValueWitnesses()->isValueInline()) {
10661072
type->vw_initializeWithTake(destObject, srcObject);
1073+
} else {
1074+
memcpy(destObject, srcObject, sizeof(uintptr_t));
10671075
}
10681076
}
10691077

@@ -1150,6 +1158,8 @@ swift_generic_initWithTake(swift::OpaqueValue *dest, swift::OpaqueValue *src,
11501158

11511159
handleRefCountsInitWithTake(metadata, reader, addrOffset, (uint8_t *)dest, (uint8_t *)src);
11521160

1161+
assert(addrOffset == metadata->vw_size());
1162+
11531163
return dest;
11541164
}
11551165

@@ -1282,12 +1292,14 @@ static void objcStrongAssignWithCopy(const Metadata *metadata,
12821292
uint8_t *dest,
12831293
uint8_t *src) {
12841294
uintptr_t _addrOffset = addrOffset;
1285-
objc_object *destObject = (objc_object*)(*(uintptr_t *)(dest + _addrOffset));
1286-
objc_object *srcObject = (objc_object*)(*(uintptr_t *)(src + _addrOffset));
1295+
uintptr_t destObject = *(uintptr_t *)(dest + _addrOffset);
1296+
uintptr_t srcObject = *(uintptr_t *)(src + _addrOffset);
12871297
memcpy(dest + _addrOffset, &srcObject, sizeof(objc_object*));
1298+
destObject &= ~_swift_abi_SwiftSpareBitsMask;
1299+
srcObject &= ~_swift_abi_SwiftSpareBitsMask;
12881300
addrOffset = _addrOffset + sizeof(objc_object*);
1289-
objc_release(destObject);
1290-
objc_retain(srcObject);
1301+
objc_release((objc_object *)destObject);
1302+
objc_retain((objc_object *)srcObject);
12911303
}
12921304
#endif
12931305

@@ -1599,7 +1611,7 @@ static void multiPayloadEnumFNAssignWithCopy(const Metadata *metadata,
15991611
if (trailingBytes)
16001612
memcpy(dest + nestedAddrOffset, src + nestedAddrOffset, trailingBytes);
16011613
return;
1602-
} else if (destTag > numPayloads) {
1614+
} else if (srcTag < numPayloads) {
16031615
addrOffset += enumSize;
16041616
size_t refCountOffset = nestedReader.peekBytes<size_t>(srcTag * sizeof(size_t));
16051617
nestedReader.skip((numPayloads * sizeof(size_t)) + refCountOffset);
@@ -1608,7 +1620,10 @@ static void multiPayloadEnumFNAssignWithCopy(const Metadata *metadata,
16081620
if (trailingBytes)
16091621
memcpy(dest + nestedAddrOffset, src + nestedAddrOffset, trailingBytes);
16101622
return;
1611-
} else if (srcTag > numPayloads) {
1623+
} else if (destTag < numPayloads) {
1624+
size_t refCountOffset =
1625+
nestedReader.peekBytes<size_t>(destTag * sizeof(size_t));
1626+
nestedReader.skip((numPayloads * sizeof(size_t)) + refCountOffset);
16121627
handleRefCountsDestroy(metadata, nestedReader, nestedAddrOffset, dest);
16131628
}
16141629

@@ -1654,7 +1669,7 @@ static void multiPayloadEnumFNResolvedAssignWithCopy(const Metadata *metadata,
16541669
if (trailingBytes)
16551670
memcpy(dest + nestedAddrOffset, src + nestedAddrOffset, trailingBytes);
16561671
return;
1657-
} else if (destTag > numPayloads) {
1672+
} else if (srcTag < numPayloads) {
16581673
addrOffset += enumSize;
16591674
size_t refCountOffset = nestedReader.peekBytes<size_t>(srcTag * sizeof(size_t));
16601675
nestedReader.skip((numPayloads * sizeof(size_t)) + refCountOffset);
@@ -1663,7 +1678,10 @@ static void multiPayloadEnumFNResolvedAssignWithCopy(const Metadata *metadata,
16631678
if (trailingBytes)
16641679
memcpy(dest + nestedAddrOffset, src + nestedAddrOffset, trailingBytes);
16651680
return;
1666-
} else if (srcTag > numPayloads) {
1681+
} else if (destTag < numPayloads) {
1682+
size_t refCountOffset =
1683+
nestedReader.peekBytes<size_t>(destTag * sizeof(size_t));
1684+
nestedReader.skip((numPayloads * sizeof(size_t)) + refCountOffset);
16671685
handleRefCountsDestroy(metadata, nestedReader, nestedAddrOffset, dest);
16681686
}
16691687

@@ -1711,7 +1729,7 @@ static void multiPayloadEnumGenericAssignWithCopy(const Metadata *metadata,
17111729
if (trailingBytes)
17121730
memcpy(dest + nestedAddrOffset, src + nestedAddrOffset, trailingBytes);
17131731
return;
1714-
} else if (destTag > numPayloads) {
1732+
} else if (srcTag < numPayloads) {
17151733
addrOffset += enumSize;
17161734
size_t refCountOffset = nestedReader.peekBytes<size_t>(srcTag * sizeof(size_t));
17171735
nestedReader.skip((numPayloads * sizeof(size_t)) + refCountOffset);
@@ -1720,7 +1738,10 @@ static void multiPayloadEnumGenericAssignWithCopy(const Metadata *metadata,
17201738
if (trailingBytes)
17211739
memcpy(dest + nestedAddrOffset, src + nestedAddrOffset, trailingBytes);
17221740
return;
1723-
} else if (srcTag > numPayloads) {
1741+
} else if (destTag < numPayloads) {
1742+
size_t refCountOffset =
1743+
nestedReader.peekBytes<size_t>(destTag * sizeof(size_t));
1744+
nestedReader.skip((numPayloads * sizeof(size_t)) + refCountOffset);
17241745
handleRefCountsDestroy(metadata, nestedReader, nestedAddrOffset, dest);
17251746
}
17261747

@@ -1784,12 +1805,17 @@ static void handleRefCountsAssignWithCopy(const Metadata *metadata,
17841805
extern "C" swift::OpaqueValue *
17851806
swift_generic_assignWithCopy(swift::OpaqueValue *dest, swift::OpaqueValue *src,
17861807
const Metadata *metadata) {
1787-
const uint8_t *layoutStr = metadata->getLayoutString();
1788-
LayoutStringReader1 reader{layoutStr + layoutStringHeaderSize};
1789-
uintptr_t addrOffset = 0;
1790-
handleRefCountsAssignWithCopy(metadata, reader, addrOffset, (uint8_t *)dest, (uint8_t *)src);
1808+
// const uint8_t *layoutStr = metadata->getLayoutString();
1809+
// LayoutStringReader1 reader{layoutStr + layoutStringHeaderSize};
1810+
// uintptr_t addrOffset = 0;
1811+
// handleRefCountsAssignWithCopy(metadata, reader, addrOffset, (uint8_t
1812+
// *)dest, (uint8_t *)src);
17911813

1792-
return dest;
1814+
// assert(addrOffset == metadata->vw_size());
1815+
swift_generic_destroy(dest, metadata);
1816+
return swift_generic_initWithCopy(dest, src, metadata);
1817+
1818+
// return dest;
17931819
}
17941820

17951821
extern "C" swift::OpaqueValue *
@@ -1864,12 +1890,13 @@ extern "C" unsigned swift_enumSimple_getEnumTag(swift::OpaqueValue *address,
18641890
uint64_t zeroTagValue, uint8_t xiTagBytesPattern,
18651891
unsigned xiTagBytesOffset, size_t payloadSize,
18661892
uint8_t numExtraTagBytes) -> unsigned {
1867-
auto xiTagBytes = 1 << (xiTagBytesPattern - 1);
1868-
uint64_t tagBytes =
1869-
readTagBytes(addr + xiTagBytesOffset, xiTagBytes) -
1870-
zeroTagValue;
1871-
if (tagBytes < payloadNumExtraInhabitants) {
1872-
return tagBytes + 1;
1893+
if (xiTagBytesPattern) {
1894+
auto xiTagBytes = 1 << (xiTagBytesPattern - 1);
1895+
uint64_t tagBytes =
1896+
readTagBytes(addr + xiTagBytesOffset, xiTagBytes) - zeroTagValue;
1897+
if (tagBytes < payloadNumExtraInhabitants) {
1898+
return tagBytes + 1;
1899+
}
18731900
}
18741901

18751902
return 0;
@@ -1917,16 +1944,18 @@ extern "C" void swift_enumSimple_destructiveInjectEnumTag(
19171944
uint64_t zeroTagValue, uint8_t xiTagBytesPattern,
19181945
unsigned xiTagBytesOffset, size_t payloadSize,
19191946
uint8_t numExtraTagBytes) -> bool {
1920-
auto xiTagBytes = 1 << (xiTagBytesPattern - 1);
1921-
if (tag <= payloadNumExtraInhabitants) {
1922-
if (numExtraTagBytes != 0)
1923-
storeEnumElement(addr + payloadSize, 0, numExtraTagBytes);
1947+
if (xiTagBytesPattern) {
1948+
auto xiTagBytes = 1 << (xiTagBytesPattern - 1);
1949+
if (tag <= payloadNumExtraInhabitants) {
1950+
if (numExtraTagBytes != 0)
1951+
storeEnumElement(addr + payloadSize, 0, numExtraTagBytes);
19241952

1925-
if (tag == 0)
1926-
return true;
1953+
if (tag == 0)
1954+
return true;
19271955

1928-
storeEnumElement(addr + xiTagBytesOffset, tag - 1 + zeroTagValue,
1929-
xiTagBytes);
1956+
storeEnumElement(addr + xiTagBytesOffset, tag - 1 + zeroTagValue,
1957+
xiTagBytes);
1958+
}
19301959
}
19311960
return true;
19321961
};

0 commit comments

Comments
 (0)