Skip to content

Commit 1a7ff9a

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 edddb75 commit 1a7ff9a

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
@@ -144,9 +144,8 @@ unsigned swift::swift_getEnumCaseSinglePayload(const OpaqueValue *value,
144144
auto *payloadWitnesses = payload->getValueWitnesses();
145145
auto size = payloadWitnesses->getSize();
146146
auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
147-
auto getExtraInhabitantIndex =
148-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(payloadWitnesses)
149-
->getExtraInhabitantIndex);
147+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
148+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
150149

151150
return getEnumTagSinglePayloadImpl(value, emptyCases, payload, size,
152151
numExtraInhabitants,
@@ -161,9 +160,8 @@ void swift::swift_storeEnumTagSinglePayload(OpaqueValue *value,
161160
auto *payloadWitnesses = payload->getValueWitnesses();
162161
auto size = payloadWitnesses->getSize();
163162
auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
164-
auto storeExtraInhabitant =
165-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(payloadWitnesses)
166-
->storeExtraInhabitant);
163+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
164+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
167165

168166
storeEnumTagSinglePayloadImpl(value, whichCase, emptyCases, payload, size,
169167
numExtraInhabitants, storeExtraInhabitant);

stdlib/public/runtime/Metadata.cpp

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,9 +1081,8 @@ static unsigned tuple_getEnumTagSinglePayload(const OpaqueValue *enumAddr,
10811081
auto *witnesses = self->getValueWitnesses();
10821082
auto size = witnesses->getSize();
10831083
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1084-
auto getExtraInhabitantIndex =
1085-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1086-
->getExtraInhabitantIndex);
1084+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1085+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
10871086

10881087
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
10891088
numExtraInhabitants,
@@ -1097,9 +1096,8 @@ tuple_storeEnumTagSinglePayload(OpaqueValue *enumAddr, unsigned whichCase,
10971096
auto *witnesses = self->getValueWitnesses();
10981097
auto size = witnesses->getSize();
10991098
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1100-
auto storeExtraInhabitant =
1101-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1102-
->storeExtraInhabitant);
1099+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1100+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
11031101

11041102
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self, size,
11051103
numExtraInhabitants, storeExtraInhabitant);
@@ -1617,9 +1615,8 @@ static unsigned pod_direct_getEnumTagSinglePayload(const OpaqueValue *enumAddr,
16171615
auto *witnesses = self->getValueWitnesses();
16181616
auto size = witnesses->getSize();
16191617
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1620-
auto getExtraInhabitantIndex =
1621-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1622-
->getExtraInhabitantIndex);
1618+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1619+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
16231620

16241621
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
16251622
numExtraInhabitants,
@@ -1633,9 +1630,8 @@ static void pod_direct_storeEnumTagSinglePayload(OpaqueValue *enumAddr,
16331630
auto *witnesses = self->getValueWitnesses();
16341631
auto size = witnesses->getSize();
16351632
auto numExtraInhabitants = witnesses->getNumExtraInhabitants();
1636-
auto storeExtraInhabitant =
1637-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(witnesses)
1638-
->storeExtraInhabitant);
1633+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(witnesses);
1634+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
16391635

16401636
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self, size,
16411637
numExtraInhabitants, storeExtraInhabitant);

stdlib/public/runtime/MetadataImpl.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -925,10 +925,8 @@ struct NonFixedValueWitnesses :
925925
const Metadata *self) {
926926
auto *payloadWitnesses = self->getValueWitnesses();
927927
auto size = payloadWitnesses->getSize();
928-
auto getExtraInhabitantIndex =
929-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(
930-
payloadWitnesses)
931-
->getExtraInhabitantIndex);
928+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
929+
auto getExtraInhabitantIndex = EIVWT ? EIVWT->getExtraInhabitantIndex : nullptr;
932930

933931
return getEnumTagSinglePayloadImpl(enumAddr, numEmptyCases, self, size,
934932
numExtraInhabitants,
@@ -942,10 +940,8 @@ struct NonFixedValueWitnesses :
942940
auto *payloadWitnesses = self->getValueWitnesses();
943941
auto size = payloadWitnesses->getSize();
944942
auto numExtraInhabitants = payloadWitnesses->getNumExtraInhabitants();
945-
auto storeExtraInhabitant =
946-
(static_cast<const ExtraInhabitantsValueWitnessTable *>(
947-
payloadWitnesses)
948-
->storeExtraInhabitant);
943+
auto EIVWT = dyn_cast<ExtraInhabitantsValueWitnessTable>(payloadWitnesses);
944+
auto storeExtraInhabitant = EIVWT ? EIVWT->storeExtraInhabitant : nullptr;
949945

950946
storeEnumTagSinglePayloadImpl(enumAddr, whichCase, numEmptyCases, self,
951947
size, numExtraInhabitants,

0 commit comments

Comments
 (0)