Skip to content

Commit b964cde

Browse files
committed
[Runtime] In various enumTagSinglePayload functions, don't read getExtraInhabitantIndex or storeExtraInhabitant unless it actually has extra inhabitants.
This code would previously read off the end of the allocated metadata to fetch these values. This was usually harmless, as the value was never used in that case. However, on rare occasions the metadata would be right before unmapped memory, and this read would crash trying to access that unmapped memory. rdar://problem/39866044
1 parent 18ec4ad commit b964cde

File tree

3 files changed

+16
-26
lines changed

3 files changed

+16
-26
lines changed

stdlib/public/runtime/Enum.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,8 @@ unsigned swift::swift_getEnumCaseSinglePayload(const OpaqueValue *value,
146146
auto *payloadWitnesses = payload->getValueWitnesses();
147147
auto size = payloadWitnesses->getSize();
148148
auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
149-
auto getExtraInhabitantIndex =
150-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(payloadWitnesses)
151-
->getExtraInhabitantIndex);
149+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
150+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
152151

153152
return getEnumTagSinglePayloadImpl(value, emptyCases, payload, size,
154153
numExtraInhabitants,
@@ -163,9 +162,8 @@ void swift::swift_storeEnumTagSinglePayload(OpaqueValue *value,
163162
auto *payloadWitnesses = payload->getValueWitnesses();
164163
auto size = payloadWitnesses->getSize();
165164
auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
166-
auto storeExtraInhabitant =
167-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(payloadWitnesses)
168-
->storeExtraInhabitant);
165+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
166+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
169167

170168
storeEnumTagSinglePayloadImpl(value, whichCase, emptyCases, payload, size,
171169
numExtraInhabitants, storeExtraInhabitant);

stdlib/public/runtime/Metadata.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,9 +1064,8 @@ static unsigned tuple_getEnumTagSinglePayload(const OpaqueValue *enumAddr,
10641064
auto *witnesses = self->getValueWitnesses();
10651065
auto size = witnesses->getSize();
10661066
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1067-
auto getExtraInhabitantIndex =
1068-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1069-
->getExtraInhabitantIndex);
1067+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1068+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
10701069

10711070
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
10721071
numExtraInhabitants,
@@ -1080,9 +1079,8 @@ tuple_storeEnumTagSinglePayload(OpaqueValue *enumAddr, unsigned whichCase,
10801079
auto *witnesses = self->getValueWitnesses();
10811080
auto size = witnesses->getSize();
10821081
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1083-
auto storeExtraInhabitant =
1084-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1085-
->storeExtraInhabitant);
1082+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1083+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
10861084

10871085
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self, size,
10881086
numExtraInhabitants, storeExtraInhabitant);
@@ -1585,9 +1583,8 @@ static unsigned pod_direct_getEnumTagSinglePayload(const OpaqueValue *enumAddr,
15851583
auto *witnesses = self->getValueWitnesses();
15861584
auto size = witnesses->getSize();
15871585
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1588-
auto getExtraInhabitantIndex =
1589-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1590-
->getExtraInhabitantIndex);
1586+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1587+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
15911588

15921589
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
15931590
numExtraInhabitants,
@@ -1601,9 +1598,8 @@ static void pod_direct_storeEnumTagSinglePayload(OpaqueValue *enumAddr,
16011598
auto *witnesses = self->getValueWitnesses();
16021599
auto size = witnesses->getSize();
16031600
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1604-
auto storeExtraInhabitant =
1605-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1606-
->storeExtraInhabitant);
1601+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1602+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
16071603

16081604
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self, size,
16091605
numExtraInhabitants, storeExtraInhabitant);

stdlib/public/runtime/MetadataImpl.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -889,10 +889,8 @@ struct NonFixedValueWitnesses :
889889
const Metadata *self) {
890890
auto *payloadWitnesses = self->getValueWitnesses();
891891
auto size = payloadWitnesses->getSize();
892-
auto getExtraInhabitantIndex =
893-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(
894-
payloadWitnesses)
895-
->getExtraInhabitantIndex);
892+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
893+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
896894

897895
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
898896
numExtraInhabitants,
@@ -906,10 +904,8 @@ struct NonFixedValueWitnesses :
906904
auto *payloadWitnesses = self->getValueWitnesses();
907905
auto size = payloadWitnesses->getSize();
908906
auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
909-
auto storeExtraInhabitant =
910-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(
911-
payloadWitnesses)
912-
->storeExtraInhabitant);
907+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
908+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
913909

914910
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self,
915911
size, numExtraInhabitants,

0 commit comments

Comments
 (0)