From 49e3f1788641fe3709644f5644048a00a3fea43b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 24 Jun 2019 17:11:16 -1000 Subject: [PATCH] Add instantiation count limiter --- src/compiler/checker.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9cb08b3e440..f4eb3940e1e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -65,6 +65,7 @@ namespace ts { let typeCount = 0; let symbolCount = 0; let enumCount = 0; + let instantiationCount = 0; let instantiationDepth = 0; let constraintDepth = 0; let currentNode: Node | undefined; @@ -11408,13 +11409,14 @@ namespace ts { if (!type || !mapper || mapper === identityMapper) { return type; } - if (instantiationDepth === 50) { + if (instantiationDepth === 50 || instantiationCount >= 5000000) { // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing // with a combination of infinite generic types that perpetually generate new type identities. We stop // the recursion here by yielding the error type. error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite); return errorType; } + instantiationCount++; instantiationDepth++; const result = instantiateTypeWorker(type, mapper); instantiationDepth--; @@ -24494,6 +24496,7 @@ namespace ts { function checkExpression(node: Expression | QualifiedName, checkMode?: CheckMode, forceTuple?: boolean): Type { const saveCurrentNode = currentNode; currentNode = node; + instantiationCount = 0; const uninstantiatedType = checkExpressionWorker(node, checkMode, forceTuple); const type = instantiateTypeWithSingleGenericCallSignature(node, uninstantiatedType, checkMode); if (isConstEnumObjectType(type)) { @@ -29204,6 +29207,7 @@ namespace ts { if (node) { const saveCurrentNode = currentNode; currentNode = node; + instantiationCount = 0; checkSourceElementWorker(node); currentNode = saveCurrentNode; } @@ -29475,6 +29479,7 @@ namespace ts { function checkDeferredNode(node: Node) { const saveCurrentNode = currentNode; currentNode = node; + instantiationCount = 0; switch (node.kind) { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: