Skip to content

Commit c3f15cb

Browse files
authored
Merge pull request #61703 from mikeash/readtypefrommetadata-recursion-limit
[Reflection] Put a recursion limit on readTypeFromMetadata.
2 parents 8349615 + 4945a56 commit c3f15cb

File tree

2 files changed

+89
-24
lines changed

2 files changed

+89
-24
lines changed

include/swift/Remote/MetadataReader.h

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,8 @@ class MetadataReader {
186186
using StoredSize = typename Runtime::StoredSize;
187187
using TargetClassMetadata = TargetClassMetadataType<Runtime>;
188188

189+
static const int defaultTypeRecursionLimit = 50;
190+
189191
private:
190192
/// The maximum number of bytes to read when reading metadata. Anything larger
191193
/// will automatically return failure. This prevents us from reading absurd
@@ -817,12 +819,25 @@ class MetadataReader {
817819
}
818820

819821
/// Given a remote pointer to metadata, attempt to turn it into a type.
820-
BuiltType readTypeFromMetadata(StoredPointer MetadataAddress,
821-
bool skipArtificialSubclasses = false) {
822+
BuiltType
823+
readTypeFromMetadata(StoredPointer MetadataAddress,
824+
bool skipArtificialSubclasses = false,
825+
int recursion_limit = defaultTypeRecursionLimit) {
822826
auto Cached = TypeCache.find(MetadataAddress);
823827
if (Cached != TypeCache.end())
824828
return Cached->second;
825829

830+
if (recursion_limit <= 0) {
831+
return nullptr;
832+
}
833+
834+
// readTypeFromMetadata calls out to various other functions which can call
835+
// back to readTypeFromMetadata. We only want to bump the recursion limit
836+
// down here, not in the other functions, so that we're only counting
837+
// recursive calls to readTypeFromMetadata. This decrement is the only place
838+
// where we'll subtract 1.
839+
recursion_limit--;
840+
826841
// If we see garbage data in the process of building a BuiltType, and get
827842
// the same metadata address again, we will hit an infinite loop.
828843
// Insert a negative result into the cache now so that, if we recur with
@@ -835,11 +850,12 @@ class MetadataReader {
835850

836851
switch (Meta->getKind()) {
837852
case MetadataKind::Class:
838-
return readNominalTypeFromClassMetadata(Meta, skipArtificialSubclasses);
853+
return readNominalTypeFromClassMetadata(Meta, recursion_limit,
854+
skipArtificialSubclasses);
839855
case MetadataKind::Struct:
840856
case MetadataKind::Enum:
841857
case MetadataKind::Optional:
842-
return readNominalTypeFromMetadata(Meta);
858+
return readNominalTypeFromMetadata(Meta, recursion_limit);
843859
case MetadataKind::Tuple: {
844860
auto tupleMeta = cast<TargetTupleTypeMetadata<Runtime>>(Meta);
845861

@@ -848,7 +864,8 @@ class MetadataReader {
848864

849865
for (unsigned i = 0, n = tupleMeta->NumElements; i != n; ++i) {
850866
auto &element = tupleMeta->getElement(i);
851-
if (auto elementType = readTypeFromMetadata(element.Type))
867+
if (auto elementType =
868+
readTypeFromMetadata(element.Type, false, recursion_limit))
852869
elementTypes.push_back(elementType);
853870
else
854871
return BuiltType();
@@ -870,7 +887,8 @@ class MetadataReader {
870887

871888
std::vector<FunctionParam<BuiltType>> Parameters;
872889
for (unsigned i = 0, n = Function->getNumParameters(); i != n; ++i) {
873-
auto ParamTypeRef = readTypeFromMetadata(Function->getParameter(i));
890+
auto ParamTypeRef = readTypeFromMetadata(Function->getParameter(i),
891+
false, recursion_limit);
874892
if (!ParamTypeRef)
875893
return BuiltType();
876894

@@ -880,7 +898,8 @@ class MetadataReader {
880898
Parameters.push_back(std::move(Param));
881899
}
882900

883-
auto Result = readTypeFromMetadata(Function->ResultType);
901+
auto Result =
902+
readTypeFromMetadata(Function->ResultType, false, recursion_limit);
884903
if (!Result)
885904
return BuiltType();
886905

@@ -894,7 +913,8 @@ class MetadataReader {
894913

895914
BuiltType globalActor = BuiltType();
896915
if (Function->hasGlobalActor()) {
897-
globalActor = readTypeFromMetadata(Function->getGlobalActor());
916+
globalActor = readTypeFromMetadata(Function->getGlobalActor(), false,
917+
recursion_limit);
898918
if (globalActor)
899919
flags = flags.withGlobalActor(true);
900920
}
@@ -929,7 +949,8 @@ class MetadataReader {
929949
BuiltType SuperclassType = BuiltType();
930950
if (Exist->Flags.hasSuperclassConstraint()) {
931951
// The superclass is stored after the list of protocols.
932-
SuperclassType = readTypeFromMetadata(Exist->getSuperclassConstraint());
952+
SuperclassType = readTypeFromMetadata(Exist->getSuperclassConstraint(),
953+
false, recursion_limit);
933954
if (!SuperclassType) return BuiltType();
934955

935956
HasExplicitAnyObject = true;
@@ -985,7 +1006,7 @@ class MetadataReader {
9851006
std::vector<BuiltType> builtArgs;
9861007
for (unsigned i = 0; i < shapeArgumentCount; ++i) {
9871008
auto remoteArg = Exist->getGeneralizationArguments()[i];
988-
auto builtArg = readTypeFromMetadata(remoteArg);
1009+
auto builtArg = readTypeFromMetadata(remoteArg, false, recursion_limit);
9891010
if (!builtArg)
9901011
return BuiltType();
9911012
builtArgs.push_back(builtArg);
@@ -1050,7 +1071,8 @@ class MetadataReader {
10501071

10511072
case MetadataKind::Metatype: {
10521073
auto Metatype = cast<TargetMetatypeMetadata<Runtime>>(Meta);
1053-
auto Instance = readTypeFromMetadata(Metatype->InstanceType);
1074+
auto Instance =
1075+
readTypeFromMetadata(Metatype->InstanceType, false, recursion_limit);
10541076
if (!Instance) return BuiltType();
10551077
auto BuiltMetatype = Builder.createMetatypeType(Instance);
10561078
TypeCache[MetadataAddress] = BuiltMetatype;
@@ -1070,7 +1092,8 @@ class MetadataReader {
10701092
}
10711093
case MetadataKind::ExistentialMetatype: {
10721094
auto Exist = cast<TargetExistentialMetatypeMetadata<Runtime>>(Meta);
1073-
auto Instance = readTypeFromMetadata(Exist->InstanceType);
1095+
auto Instance =
1096+
readTypeFromMetadata(Exist->InstanceType, false, recursion_limit);
10741097
if (!Instance) return BuiltType();
10751098
auto BuiltExist = Builder.createExistentialMetatypeType(Instance);
10761099
TypeCache[MetadataAddress] = BuiltExist;
@@ -2959,8 +2982,9 @@ class MetadataReader {
29592982
// TODO: We need to be able to produce protocol conformances for each
29602983
// substitution type as well in order to accurately rebuild bound generic
29612984
// types or types in protocol-constrained inner contexts.
2962-
std::vector<BuiltType>
2963-
getGenericSubst(MetadataRef metadata, ContextDescriptorRef descriptor) {
2985+
std::vector<BuiltType> getGenericSubst(MetadataRef metadata,
2986+
ContextDescriptorRef descriptor,
2987+
int recursion_limit) {
29642988
auto generics = descriptor->getGenericContext();
29652989
if (!generics)
29662990
return {};
@@ -2997,8 +3021,8 @@ class MetadataReader {
29973021
return {};
29983022
}
29993023
genericArgsAddr += sizeof(StoredPointer);
3000-
3001-
auto builtArg = readTypeFromMetadata(arg);
3024+
3025+
auto builtArg = readTypeFromMetadata(arg, false, recursion_limit);
30023026
if (!builtArg)
30033027
return {};
30043028
builtSubsts.push_back(builtArg);
@@ -3018,8 +3042,10 @@ class MetadataReader {
30183042
return builtSubsts;
30193043
}
30203044

3021-
BuiltType readNominalTypeFromMetadata(MetadataRef origMetadata,
3022-
bool skipArtificialSubclasses = false) {
3045+
BuiltType
3046+
readNominalTypeFromMetadata(MetadataRef origMetadata,
3047+
int recursion_limit = defaultTypeRecursionLimit,
3048+
bool skipArtificialSubclasses = false) {
30233049
auto metadata = origMetadata;
30243050
auto descriptorAddress =
30253051
readAddressOfNominalTypeDescriptor(metadata,
@@ -3049,7 +3075,8 @@ class MetadataReader {
30493075
BuiltType nominal;
30503076
if (descriptor->isGeneric()) {
30513077
// Resolve the generic arguments.
3052-
auto builtGenerics = getGenericSubst(metadata, descriptor);
3078+
auto builtGenerics =
3079+
getGenericSubst(metadata, descriptor, recursion_limit);
30533080
if (builtGenerics.empty())
30543081
return BuiltType();
30553082
nominal = Builder.createBoundGenericType(typeDecl, builtGenerics);
@@ -3071,11 +3098,14 @@ class MetadataReader {
30713098
return nominal;
30723099
}
30733100

3074-
BuiltType readNominalTypeFromClassMetadata(MetadataRef origMetadata,
3075-
bool skipArtificialSubclasses = false) {
3101+
BuiltType
3102+
readNominalTypeFromClassMetadata(MetadataRef origMetadata,
3103+
int recursion_limit,
3104+
bool skipArtificialSubclasses = false) {
30763105
auto classMeta = cast<TargetClassMetadata>(origMetadata);
30773106
if (classMeta->isTypeMetadata())
3078-
return readNominalTypeFromMetadata(origMetadata, skipArtificialSubclasses);
3107+
return readNominalTypeFromMetadata(origMetadata, recursion_limit,
3108+
skipArtificialSubclasses);
30793109

30803110
std::string className;
30813111
auto origMetadataPtr = getAddress(origMetadata);
@@ -3088,8 +3118,9 @@ class MetadataReader {
30883118
if (!stripSignedPointer(classMeta->Superclass))
30893119
return BuiltType();
30903120

3091-
BuiltObjCClass = readTypeFromMetadata(
3092-
stripSignedPointer(classMeta->Superclass), skipArtificialSubclasses);
3121+
BuiltObjCClass =
3122+
readTypeFromMetadata(stripSignedPointer(classMeta->Superclass),
3123+
skipArtificialSubclasses, recursion_limit);
30933124
}
30943125

30953126
TypeCache[origMetadataPtr] = BuiltObjCClass;
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -g -lswiftSwiftReflectionTest %s -o %t/reflect_deep_generic
3+
// RUN: %target-codesign %t/reflect_deep_generic
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_deep_generic | %FileCheck %s
6+
7+
// REQUIRES: reflection_test_support
8+
// REQUIRES: executable_test
9+
// UNSUPPORTED: use_os_stdlib
10+
11+
import SwiftReflectionTest
12+
13+
protocol Nester {
14+
func nest() -> Nester
15+
}
16+
17+
class C<T>: Nester {
18+
func nest() -> Nester {
19+
return C<Self>()
20+
}
21+
}
22+
23+
var nester: Nester = C<Int>()
24+
for _ in 0..<10000 {
25+
nester = nester.nest()
26+
}
27+
28+
// This will fail due to the excessively nested type, but we're making sure it
29+
// fails gracefully and doesn't crash.
30+
reflect(object: nester as AnyObject)
31+
32+
doneReflecting()
33+
34+
// CHECK: Done.

0 commit comments

Comments
 (0)