From 84c0f2c8806ff8aaff74f1c0bae946fbdc830479 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Fri, 24 Mar 2023 21:42:37 +0000 Subject: [PATCH] Sanitize arguments of super/redirecting constructor invocations. We have a spike of crashes internally. Change-Id: If7c280692ac0acdd2e4a4acd6096a4669746069c Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/291120 Commit-Queue: Konstantin Shcheglov Reviewed-by: Brian Wilkerson --- .../lib/src/dart/analysis/driver.dart | 2 +- .../lib/src/summary2/detach_nodes.dart | 20 +++-- .../test/src/summary/elements_test.dart | 87 ++++++++++++++++++- 3 files changed, 100 insertions(+), 9 deletions(-) diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart index 4ceb19b57ef..2669b339a1f 100644 --- a/pkg/analyzer/lib/src/dart/analysis/driver.dart +++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart @@ -87,7 +87,7 @@ import 'package:analyzer/src/utilities/uri_cache.dart'; /// TODO(scheglov) Clean up the list of implicitly analyzed files. class AnalysisDriver implements AnalysisDriverGeneric { /// The version of data format, should be incremented on every format change. - static const int DATA_VERSION = 264; + static const int DATA_VERSION = 265; /// The number of exception contexts allowed to write. Once this field is /// zero, we stop writing any new exception contexts in this process. diff --git a/pkg/analyzer/lib/src/summary2/detach_nodes.dart b/pkg/analyzer/lib/src/summary2/detach_nodes.dart index b6213ccefe4..019c21a61a7 100644 --- a/pkg/analyzer/lib/src/summary2/detach_nodes.dart +++ b/pkg/analyzer/lib/src/summary2/detach_nodes.dart @@ -39,6 +39,10 @@ class _Visitor extends GeneralizingElementVisitor { final expression = initializer.expression; final replacement = replaceNotSerializableNode(expression); initializer.expression = replacement; + } else if (initializer is RedirectingConstructorInvocationImpl) { + _sanitizeArguments(initializer.argumentList.arguments); + } else if (initializer is SuperConstructorInvocationImpl) { + _sanitizeArguments(initializer.argumentList.arguments); } } @@ -52,13 +56,7 @@ class _Visitor extends GeneralizingElementVisitor { for (final annotation in element.metadata) { final ast = (annotation as ElementAnnotationImpl).annotationAst; _detachNode(ast); - // Sanitize arguments. - final arguments = ast.arguments?.arguments; - if (arguments != null) { - for (var i = 0; i < arguments.length; i++) { - arguments[i] = replaceNotSerializableNode(arguments[i]); - } - } + _sanitizeArguments(ast.arguments?.arguments); } super.visitElement(element); } @@ -108,4 +106,12 @@ class _Visitor extends GeneralizingElementVisitor { node.endToken.next = null; } } + + void _sanitizeArguments(List? arguments) { + if (arguments != null) { + for (var i = 0; i < arguments.length; i++) { + arguments[i] = replaceNotSerializableNode(arguments[i]); + } + } + } } diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart index 8fbef6781a5..717317ac169 100644 --- a/pkg/analyzer/test/src/summary/elements_test.dart +++ b/pkg/analyzer/test/src/summary/elements_test.dart @@ -12911,7 +12911,7 @@ library '''); } - test_const_invalid_functionExpression_inConstructorInitializer() async { + test_const_invalid_functionExpression_constructorFieldInitializer() async { var library = await buildLibrary(''' class A { final Object? foo; @@ -12968,6 +12968,91 @@ library '''); } + test_const_invalid_functionExpression_redirectingConstructorInvocation() async { + var library = await buildLibrary(''' +class A { + const A(Object a, Object b); + const A.named() : this(0, () => 0); +} +'''); + checkElementText(library, r''' +library + definingUnit + classes + class A @6 + constructors + const @18 + parameters + requiredPositional a @27 + type: Object + requiredPositional b @37 + type: Object + const named @51 + periodOffset: 50 + nameEnd: 56 + constantInitializers + RedirectingConstructorInvocation + thisKeyword: this @61 + argumentList: ArgumentList + leftParenthesis: ( @65 + arguments + IntegerLiteral + literal: 0 @66 + staticType: int + SimpleIdentifier + token: _notSerializableExpression @-1 + staticElement: + staticType: null + rightParenthesis: ) @76 + staticElement: self::@class::A::@constructor::new + redirectedConstructor: self::@class::A::@constructor::new +'''); + } + + test_const_invalid_functionExpression_superConstructorInvocation() async { + var library = await buildLibrary(''' +class A { + const A(Object a, Object b); +} +class B extends A { + const B() : super(0, () => 0); +} +'''); + checkElementText(library, r''' +library + definingUnit + classes + class A @6 + constructors + const @18 + parameters + requiredPositional a @27 + type: Object + requiredPositional b @37 + type: Object + class B @49 + supertype: A + constructors + const @71 + constantInitializers + SuperConstructorInvocation + superKeyword: super @77 + argumentList: ArgumentList + leftParenthesis: ( @82 + arguments + IntegerLiteral + literal: 0 @83 + staticType: int + SimpleIdentifier + token: _notSerializableExpression @-1 + staticElement: + staticType: null + rightParenthesis: ) @93 + staticElement: self::@class::A::@constructor::new + superConstructor: self::@class::A::@constructor::new +'''); + } + @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/44522') test_const_invalid_intLiteral() async { var library = await buildLibrary(r'''