Skip to content

Commit d435af4

Browse files
authored
Merge pull request #37863 from mikeash/metadata-reader-sane-sizes
[Reflection] Sanity-check metadata sizes in MetadataReader before reading.
2 parents b001b0b + ebd9c21 commit d435af4

File tree

2 files changed

+42
-34
lines changed

2 files changed

+42
-34
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -170,21 +170,24 @@ class MetadataReader {
170170
using StoredSize = typename Runtime::StoredSize;
171171

172172
private:
173+
/// The maximum number of bytes to read when reading metadata. Anything larger
174+
/// will automatically return failure. This prevents us from reading absurd
175+
/// amounts of data when we encounter corrupt values for sizes/counts.
176+
static const uint64_t MaxMetadataSize = 1048576; // 1MB
177+
173178
/// A cache of built types, keyed by the address of the type.
174179
std::unordered_map<StoredPointer, BuiltType> TypeCache;
175180

176-
using MetadataRef = RemoteRef<TargetMetadata<Runtime>>;
177-
using OwnedMetadataRef =
178-
std::unique_ptr<const TargetMetadata<Runtime>, delete_with_free>;
181+
using MetadataRef = RemoteRef<const TargetMetadata<Runtime>>;
182+
using OwnedMetadataRef = MemoryReader::ReadBytesResult;
179183

180184
/// A cache of read type metadata, keyed by the address of the metadata.
181185
std::unordered_map<StoredPointer, OwnedMetadataRef>
182186
MetadataCache;
183187

184-
using ContextDescriptorRef = RemoteRef<TargetContextDescriptor<Runtime>>;
185-
using OwnedContextDescriptorRef =
186-
std::unique_ptr<const TargetContextDescriptor<Runtime>,
187-
delete_with_free>;
188+
using ContextDescriptorRef =
189+
RemoteRef<const TargetContextDescriptor<Runtime>>;
190+
using OwnedContextDescriptorRef = MemoryReader::ReadBytesResult;
188191

189192
/// A reference to a context descriptor that may be in an unloaded image.
190193
class ParentContextDescriptorRef {
@@ -984,7 +987,9 @@ class MetadataReader {
984987

985988
auto cached = ContextDescriptorCache.find(address);
986989
if (cached != ContextDescriptorCache.end())
987-
return ContextDescriptorRef(address, cached->second.get());
990+
return ContextDescriptorRef(
991+
address, reinterpret_cast<const TargetContextDescriptor<Runtime> *>(
992+
cached->second.get()));
988993

989994
// Read the flags to figure out how much space we should read.
990995
ContextDescriptorFlags flags;
@@ -993,9 +998,9 @@ class MetadataReader {
993998
return nullptr;
994999

9951000
TypeContextDescriptorFlags typeFlags(flags.getKindSpecificFlags());
996-
unsigned baseSize = 0;
997-
unsigned genericHeaderSize = sizeof(GenericContextDescriptorHeader);
998-
unsigned metadataInitSize = 0;
1001+
uint64_t baseSize = 0;
1002+
uint64_t genericHeaderSize = sizeof(GenericContextDescriptorHeader);
1003+
uint64_t metadataInitSize = 0;
9991004
bool hasVTable = false;
10001005

10011006
auto readMetadataInitSize = [&]() -> unsigned {
@@ -1059,7 +1064,7 @@ class MetadataReader {
10591064
// Determine the full size of the descriptor. This is reimplementing a fair
10601065
// bit of TrailingObjects but for out-of-process; maybe there's a way to
10611066
// factor the layout stuff out...
1062-
unsigned genericsSize = 0;
1067+
uint64_t genericsSize = 0;
10631068
if (flags.isGeneric()) {
10641069
GenericContextDescriptorHeader header;
10651070
auto headerAddr = address
@@ -1077,7 +1082,7 @@ class MetadataReader {
10771082
* sizeof(TargetGenericRequirementDescriptor<Runtime>);
10781083
}
10791084

1080-
unsigned vtableSize = 0;
1085+
uint64_t vtableSize = 0;
10811086
if (hasVTable) {
10821087
TargetVTableDescriptorHeader<Runtime> header;
10831088
auto headerAddr = address
@@ -1092,22 +1097,20 @@ class MetadataReader {
10921097
vtableSize = sizeof(header)
10931098
+ header.VTableSize * sizeof(TargetMethodDescriptor<Runtime>);
10941099
}
1095-
1096-
unsigned size = baseSize + genericsSize + metadataInitSize + vtableSize;
1097-
auto buffer = (uint8_t *)malloc(size);
1098-
if (buffer == nullptr) {
1100+
1101+
uint64_t size = baseSize + genericsSize + metadataInitSize + vtableSize;
1102+
if (size > MaxMetadataSize)
10991103
return nullptr;
1100-
}
1101-
if (!Reader->readBytes(RemoteAddress(address), buffer, size)) {
1102-
free(buffer);
1104+
auto readResult = Reader->readBytes(RemoteAddress(address), size);
1105+
if (!readResult)
11031106
return nullptr;
1104-
}
11051107

1106-
auto descriptor
1107-
= reinterpret_cast<TargetContextDescriptor<Runtime> *>(buffer);
1108+
auto descriptor =
1109+
reinterpret_cast<const TargetContextDescriptor<Runtime> *>(
1110+
readResult.get());
11081111

11091112
ContextDescriptorCache.insert(
1110-
std::make_pair(address, OwnedContextDescriptorRef(descriptor)));
1113+
std::make_pair(address, std::move(readResult)));
11111114
return ContextDescriptorRef(address, descriptor);
11121115
}
11131116

@@ -1633,7 +1636,9 @@ class MetadataReader {
16331636
MetadataRef readMetadata(StoredPointer address) {
16341637
auto cached = MetadataCache.find(address);
16351638
if (cached != MetadataCache.end())
1636-
return MetadataRef(address, cached->second.get());
1639+
return MetadataRef(address,
1640+
reinterpret_cast<const TargetMetadata<Runtime> *>(
1641+
cached->second.get()));
16371642

16381643
StoredPointer KindValue = 0;
16391644
if (!Reader->readInteger(RemoteAddress(address), &KindValue))
@@ -1807,18 +1812,15 @@ class MetadataReader {
18071812
}
18081813

18091814
MetadataRef _readMetadata(StoredPointer address, size_t sizeAfter) {
1810-
auto size = sizeAfter;
1811-
uint8_t *buffer = (uint8_t *) malloc(size);
1812-
if (!buffer)
1815+
if (sizeAfter > MaxMetadataSize)
18131816
return nullptr;
1814-
1815-
if (!Reader->readBytes(RemoteAddress(address), buffer, size)) {
1816-
free(buffer);
1817+
auto readResult = Reader->readBytes(RemoteAddress(address), sizeAfter);
1818+
if (!readResult)
18171819
return nullptr;
1818-
}
18191820

1820-
auto metadata = reinterpret_cast<TargetMetadata<Runtime>*>(buffer);
1821-
MetadataCache.insert(std::make_pair(address, OwnedMetadataRef(metadata)));
1821+
auto metadata =
1822+
reinterpret_cast<const TargetMetadata<Runtime> *>(readResult.get());
1823+
MetadataCache.insert(std::make_pair(address, std::move(readResult)));
18221824
return MetadataRef(address, metadata);
18231825
}
18241826

test/stdlib/symbol-visibility-linux.test-sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
// RUN: -e _ZNSt6vectorIjSaIjEE13_M_insert_auxIJjEEEvN9__gnu_cxx17__normal_iteratorIPjS1_EEDpOT_ \
2020
// RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE19_M_emplace_back_auxIJS6_EEEvDpOT_ \
2121
// RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE17_M_realloc_insertIJS6_EEEvN9__gnu_cxx17__normal_iteratorIPS6_S8_EEDpOT_ \
22+
// RUN: -e _ZNSt10_HashtableImSt4pairIKmSt10unique_ptrIKvSt8functionIFvPS3_EEEESaIS9_ENSt8__detail10_Select1stESt8equal_toImESt4hashImENSB_18_Mod_range_hashingENSB_20_Default_ranged_hashENSB_20_Prime_rehash_policyENSB_17_Hashtable_traitsILb0ELb0ELb1EEEE10_M_emplaceIJS0_ImS8_EEEES0_INSB_14_Node_iteratorIS9_Lb0ELb0EEEbESt17integral_constantIbLb1EEDpOT_ \
23+
// RUN: -e _ZNSt10_HashtableImSt4pairIKmSt10unique_ptrIKvSt8functionIFvPS3_EEEESaIS9_ENSt8__detail10_Select1stESt8equal_toImESt4hashImENSB_18_Mod_range_hashingENSB_20_Default_ranged_hashENSB_20_Prime_rehash_policyENSB_17_Hashtable_traitsILb0ELb0ELb1EEEE13_M_rehash_auxEmSt17integral_constantIbLb1EE \
24+
// RUN: -e _ZNSt10_HashtableImSt4pairIKmSt10unique_ptrIKvSt8functionIFvPS3_EEEESaIS9_ENSt8__detail10_Select1stESt8equal_toImESt4hashImENSB_18_Mod_range_hashingENSB_20_Default_ranged_hashENSB_20_Prime_rehash_policyENSB_17_Hashtable_traitsILb0ELb0ELb1EEEED2Ev \
2225
// RUN: -e _ZNSt3_V28__rotateIPcEET_S2_S2_S2_St26random_access_iterator_tag \
2326
// RUN: -e _ZN9__gnu_cxx12__to_xstringINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEcEET_PFiPT0_mPKS8_P13__va_list_tagEmSB_z \
2427
// RUN: -e _ZN9__gnu_cxx12__to_xstringINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEcEET_PFiPT0_mPKS8_St9__va_listEmSB_z \
@@ -38,6 +41,9 @@
3841
// RUN: -e _ZNSt6vectorIjSaIjEE13_M_insert_auxIJjEEEvN9__gnu_cxx17__normal_iteratorIPjS1_EEDpOT_ \
3942
// RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE19_M_emplace_back_auxIJS6_EEEvDpOT_ \
4043
// RUN: -e _ZNSt6vectorISt10unique_ptrIKvSt8functionIFvPS1_EEESaIS6_EE17_M_realloc_insertIJS6_EEEvN9__gnu_cxx17__normal_iteratorIPS6_S8_EEDpOT_ \
44+
// RUN: -e _ZNSt10_HashtableImSt4pairIKmSt10unique_ptrIKvSt8functionIFvPS3_EEEESaIS9_ENSt8__detail10_Select1stESt8equal_toImESt4hashImENSB_18_Mod_range_hashingENSB_20_Default_ranged_hashENSB_20_Prime_rehash_policyENSB_17_Hashtable_traitsILb0ELb0ELb1EEEE10_M_emplaceIJS0_ImS8_EEEES0_INSB_14_Node_iteratorIS9_Lb0ELb0EEEbESt17integral_constantIbLb1EEDpOT_ \
45+
// RUN: -e _ZNSt10_HashtableImSt4pairIKmSt10unique_ptrIKvSt8functionIFvPS3_EEEESaIS9_ENSt8__detail10_Select1stESt8equal_toImESt4hashImENSB_18_Mod_range_hashingENSB_20_Default_ranged_hashENSB_20_Prime_rehash_policyENSB_17_Hashtable_traitsILb0ELb0ELb1EEEE13_M_rehash_auxEmSt17integral_constantIbLb1EE \
46+
// RUN: -e _ZNSt10_HashtableImSt4pairIKmSt10unique_ptrIKvSt8functionIFvPS3_EEEESaIS9_ENSt8__detail10_Select1stESt8equal_toImESt4hashImENSB_18_Mod_range_hashingENSB_20_Default_ranged_hashENSB_20_Prime_rehash_policyENSB_17_Hashtable_traitsILb0ELb0ELb1EEEED2Ev \
4147
// RUN: -e _ZNSt3_V28__rotateIPcEET_S2_S2_S2_St26random_access_iterator_tag \
4248
// RUN: -e _ZN9__gnu_cxx12__to_xstringINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEcEET_PFiPT0_mPKS8_P13__va_list_tagEmSB_z \
4349
// RUN: -e _ZN9__gnu_cxx12__to_xstringINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEcEET_PFiPT0_mPKS8_St9__va_listEmSB_z \

0 commit comments

Comments
 (0)