@@ -170,21 +170,24 @@ class MetadataReader {
170170 using StoredSize = typename Runtime::StoredSize;
171171
172172private:
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
0 commit comments