Skip to content

Commit b1aafe3

Browse files
bitjammertkremenek
authored andcommitted
[Remote] Cache built types when reading metadata (#2871)
If bad data is fed to the reader, it might be convinced it's looking at a generic type. If the generic type parameter also happens to be the same metadata pointer, an infinite recursion results. To prevent this, insert an invalid type into the cache at the start of the read. If we then ask for that same metadata pointer again, we'll return the invalid/empty built type. This also might improve performance a little by preventing rereading and rebuilding types. rdar://problem/26529650
1 parent 14a4304 commit b1aafe3

File tree

1 file changed

+38
-13
lines changed

1 file changed

+38
-13
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,13 @@ class MetadataReader {
600600
if (Cached != TypeCache.end())
601601
return Cached->second;
602602

603+
// If we see garbage data in the process of building a BuiltType, and get
604+
// the same metadata address again, we will hit an infinite loop.
605+
// Insert a negative result into the cache now so that, if we recur with
606+
// the same address, we will return the negative result with the check
607+
// just above.
608+
TypeCache.insert({MetadataAddress, BuiltType()});
609+
603610
auto Meta = readMetadata(MetadataAddress);
604611
if (!Meta) return BuiltType();
605612

@@ -639,8 +646,10 @@ class MetadataReader {
639646
!Reader->readString(RemoteAddress(tupleMeta->Labels), labels))
640647
return BuiltType();
641648

642-
return Builder.createTupleType(elementTypes, std::move(labels),
643-
/*variadic*/ false);
649+
auto BuiltTuple = Builder.createTupleType(elementTypes, std::move(labels),
650+
/*variadic*/ false);
651+
TypeCache[MetadataAddress] = BuiltTuple;
652+
return BuiltTuple;
644653
}
645654
case MetadataKind::Function: {
646655
auto Function = cast<TargetFunctionTypeMetadata<Runtime>>(Meta);
@@ -673,8 +682,11 @@ class MetadataReader {
673682

674683
auto flags = FunctionTypeFlags().withConvention(Function->getConvention())
675684
.withThrows(Function->throws());
676-
return Builder.createFunctionType(Arguments, ArgumentIsInOut,
677-
Result, flags);
685+
auto BuiltFunction = Builder.createFunctionType(Arguments,
686+
ArgumentIsInOut,
687+
Result, flags);
688+
TypeCache[MetadataAddress] = BuiltFunction;
689+
return BuiltFunction;
678690
}
679691
case MetadataKind::Existential: {
680692
auto Exist = cast<TargetExistentialTypeMetadata<Runtime>>(Meta);
@@ -684,7 +696,7 @@ class MetadataReader {
684696
auto ProtocolDescriptor = readProtocolDescriptor(ProtocolAddress);
685697
if (!ProtocolDescriptor)
686698
return BuiltType();
687-
699+
688700
std::string MangledName;
689701
if (!Reader->readString(RemoteAddress(ProtocolDescriptor->Name),
690702
MangledName))
@@ -696,13 +708,17 @@ class MetadataReader {
696708

697709
Protocols.push_back(Protocol);
698710
}
699-
return Builder.createProtocolCompositionType(Protocols);
711+
auto BuiltExist = Builder.createProtocolCompositionType(Protocols);
712+
TypeCache[MetadataAddress] = BuiltExist;
713+
return BuiltExist;
700714
}
701715
case MetadataKind::Metatype: {
702716
auto Metatype = cast<TargetMetatypeMetadata<Runtime>>(Meta);
703717
auto Instance = readTypeFromMetadata(Metatype->InstanceType);
704718
if (!Instance) return BuiltType();
705-
return Builder.createMetatypeType(Instance);
719+
auto BuiltMetatype = Builder.createMetatypeType(Instance);
720+
TypeCache[MetadataAddress] = BuiltMetatype;
721+
return BuiltMetatype;
706722
}
707723
case MetadataKind::ObjCClassWrapper: {
708724
auto objcWrapper = cast<TargetObjCClassWrapperMetadata<Runtime>>(Meta);
@@ -712,13 +728,17 @@ class MetadataReader {
712728
if (!readObjCClassName(classAddress, className))
713729
return BuiltType();
714730

715-
return Builder.createObjCClassType(std::move(className));
731+
auto BuiltObjCClass = Builder.createObjCClassType(std::move(className));
732+
TypeCache[MetadataAddress] = BuiltObjCClass;
733+
return BuiltObjCClass;
716734
}
717735
case MetadataKind::ExistentialMetatype: {
718736
auto Exist = cast<TargetExistentialMetatypeMetadata<Runtime>>(Meta);
719737
auto Instance = readTypeFromMetadata(Exist->InstanceType);
720738
if (!Instance) return BuiltType();
721-
return Builder.createExistentialMetatypeType(Instance);
739+
auto BuiltExist = Builder.createExistentialMetatypeType(Instance);
740+
TypeCache[MetadataAddress] = BuiltExist;
741+
return BuiltExist;
722742
}
723743
case MetadataKind::ForeignClass: {
724744
auto namePtrAddress =
@@ -730,15 +750,20 @@ class MetadataReader {
730750
std::string name;
731751
if (!Reader->readString(RemoteAddress(namePtr), name))
732752
return BuiltType();
733-
return Builder.createForeignClassType(std::move(name));
753+
auto BuiltForeign = Builder.createForeignClassType(std::move(name));
754+
TypeCache[MetadataAddress] = BuiltForeign;
755+
return BuiltForeign;
734756
}
735757
case MetadataKind::HeapLocalVariable:
736758
case MetadataKind::HeapGenericLocalVariable:
737759
case MetadataKind::ErrorObject:
738760
// Treat these all as Builtin.NativeObject for type lowering purposes.
739761
return Builder.createBuiltinType("Bo");
740-
case MetadataKind::Opaque:
741-
return Builder.getOpaqueType();
762+
case MetadataKind::Opaque: {
763+
auto BuiltOpaque = Builder.getOpaqueType();
764+
TypeCache[MetadataAddress] = BuiltOpaque;
765+
return BuiltOpaque;
766+
}
742767
}
743768
}
744769

@@ -1165,7 +1190,7 @@ class MetadataReader {
11651190
}
11661191
if (!nominal) return BuiltType();
11671192

1168-
TypeCache.insert({metadata.getAddress(), nominal});
1193+
TypeCache[metadata.getAddress()] = nominal;
11691194
return nominal;
11701195
}
11711196

0 commit comments

Comments
 (0)