@@ -170,21 +170,24 @@ class MetadataReader {
170
170
using StoredSize = typename Runtime::StoredSize;
171
171
172
172
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
+
173
178
// / A cache of built types, keyed by the address of the type.
174
179
std::unordered_map<StoredPointer, BuiltType> TypeCache;
175
180
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;
179
183
180
184
// / A cache of read type metadata, keyed by the address of the metadata.
181
185
std::unordered_map<StoredPointer, OwnedMetadataRef>
182
186
MetadataCache;
183
187
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;
188
191
189
192
// / A reference to a context descriptor that may be in an unloaded image.
190
193
class ParentContextDescriptorRef {
@@ -984,7 +987,9 @@ class MetadataReader {
984
987
985
988
auto cached = ContextDescriptorCache.find (address);
986
989
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 ()));
988
993
989
994
// Read the flags to figure out how much space we should read.
990
995
ContextDescriptorFlags flags;
@@ -993,9 +998,9 @@ class MetadataReader {
993
998
return nullptr ;
994
999
995
1000
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 ;
999
1004
bool hasVTable = false ;
1000
1005
1001
1006
auto readMetadataInitSize = [&]() -> unsigned {
@@ -1059,7 +1064,7 @@ class MetadataReader {
1059
1064
// Determine the full size of the descriptor. This is reimplementing a fair
1060
1065
// bit of TrailingObjects but for out-of-process; maybe there's a way to
1061
1066
// factor the layout stuff out...
1062
- unsigned genericsSize = 0 ;
1067
+ uint64_t genericsSize = 0 ;
1063
1068
if (flags.isGeneric ()) {
1064
1069
GenericContextDescriptorHeader header;
1065
1070
auto headerAddr = address
@@ -1077,7 +1082,7 @@ class MetadataReader {
1077
1082
* sizeof (TargetGenericRequirementDescriptor<Runtime>);
1078
1083
}
1079
1084
1080
- unsigned vtableSize = 0 ;
1085
+ uint64_t vtableSize = 0 ;
1081
1086
if (hasVTable) {
1082
1087
TargetVTableDescriptorHeader<Runtime> header;
1083
1088
auto headerAddr = address
@@ -1092,22 +1097,20 @@ class MetadataReader {
1092
1097
vtableSize = sizeof (header)
1093
1098
+ header.VTableSize * sizeof (TargetMethodDescriptor<Runtime>);
1094
1099
}
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)
1099
1103
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)
1103
1106
return nullptr ;
1104
- }
1105
1107
1106
- auto descriptor
1107
- = reinterpret_cast <TargetContextDescriptor<Runtime> *>(buffer);
1108
+ auto descriptor =
1109
+ reinterpret_cast <const TargetContextDescriptor<Runtime> *>(
1110
+ readResult.get ());
1108
1111
1109
1112
ContextDescriptorCache.insert (
1110
- std::make_pair (address, OwnedContextDescriptorRef (descriptor )));
1113
+ std::make_pair (address, std::move (readResult )));
1111
1114
return ContextDescriptorRef (address, descriptor);
1112
1115
}
1113
1116
@@ -1633,7 +1636,9 @@ class MetadataReader {
1633
1636
MetadataRef readMetadata (StoredPointer address) {
1634
1637
auto cached = MetadataCache.find (address);
1635
1638
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 ()));
1637
1642
1638
1643
StoredPointer KindValue = 0 ;
1639
1644
if (!Reader->readInteger (RemoteAddress (address), &KindValue))
@@ -1807,18 +1812,15 @@ class MetadataReader {
1807
1812
}
1808
1813
1809
1814
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)
1813
1816
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)
1817
1819
return nullptr ;
1818
- }
1819
1820
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)));
1822
1824
return MetadataRef (address, metadata);
1823
1825
}
1824
1826
0 commit comments