Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Awaiting for a Future returning a class that implements Finalizable in a for-in loop causes a crash #51538

Closed
halildurmus opened this issue Feb 26, 2023 · 5 comments
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi

Comments

@halildurmus
Copy link
Contributor

halildurmus commented Feb 26, 2023

import 'dart:ffi';

class Foo implements Finalizable {}

Future<Foo> bar() => Future.value(Foo());

void main() async {
  for (final element in [await bar()]) {
    print(element);
  }
}

Running the above program causes this crash:

Null check operator used on a null value
#0      BinaryPrinter._getVariableIndex (package:kernel/binary/ast_to_binary.dart:83:17)
#1      BinaryPrinter.visitVariableGet (package:kernel/binary/ast_to_binary.dart:1575:17)
#2      VariableGet.accept (package:kernel/ast.dart:4443:44)
#3      BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#4      BinaryPrinter.writeNodeList (package:kernel/binary/ast_to_binary.dart:347:7)
#5      BinaryPrinter.visitArguments (package:kernel/binary/ast_to_binary.dart:1873:5)
#6      Arguments.accept (package:kernel/ast.dart:5734:38)
#7      BinaryPrinter.writeArgumentsNode (package:kernel/binary/ast_to_binary.dart:460:10)
#8      BinaryPrinter.visitStaticInvocation (package:kernel/binary/ast_to_binary.dart:1856:5)
#9      StaticInvocation.accept (package:kernel/ast.dart:7017:44)
#10     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#11     BinaryPrinter.visitExpressionStatement (package:kernel/binary/ast_to_binary.dart:2185:5)
#12     ExpressionStatement.accept (package:kernel/ast.dart:9703:43)
#13     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#14     BinaryPrinter.writeNodeList (package:kernel/binary/ast_to_binary.dart:347:7)
#15     BinaryPrinter.visitBlockExpression (package:kernel/binary/ast_to_binary.dart:2150:5)
#16     BlockExpression.accept (package:kernel/ast.dart:9336:44)
#17     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#18     BinaryPrinter.visitAwaitExpression (package:kernel/binary/ast_to_binary.dart:2121:5)
#19     AwaitExpression.accept (package:kernel/ast.dart:9085:44)
#20     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#21     BinaryPrinter.writeNodeList (package:kernel/binary/ast_to_binary.dart:347:7)
#22     BinaryPrinter.visitArguments (package:kernel/binary/ast_to_binary.dart:1873:5)
#23     Arguments.accept (package:kernel/ast.dart:5734:38)
#24     BinaryPrinter.writeArgumentsNode (package:kernel/binary/ast_to_binary.dart:460:10)
#25     BinaryPrinter.visitStaticInvocation (package:kernel/binary/ast_to_binary.dart:1856:5)
#26     StaticInvocation.accept (package:kernel/ast.dart:7017:44)
#27     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#28     BinaryPrinter.visitInstanceGet (package:kernel/binary/ast_to_binary.dart:1621:5)
#29     InstanceGet.accept (package:kernel/ast.dart:4822:44)
#30     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#31     BinaryPrinter.writeOptionalNode (package:kernel/binary/ast_to_binary.dart:545:7)
#32     BinaryPrinter.writeVariableDeclaration (package:kernel/binary/ast_to_binary.dart:2400:5)
#33     BinaryPrinter.visitVariableDeclaration (package:kernel/binary/ast_to_binary.dart:2386:5)
#34     VariableDeclaration.accept (package:kernel/ast.dart:11346:43)
#35     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#36     BinaryPrinter.writeNodeList (package:kernel/binary/ast_to_binary.dart:347:7)
#37     BinaryPrinter.visitBlock (package:kernel/binary/ast_to_binary.dart:2196:5)
#38     Block.accept (package:kernel/ast.dart:9759:43)
#39     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#40     BinaryPrinter.writeNodeList (package:kernel/binary/ast_to_binary.dart:347:7)
#41     BinaryPrinter.visitBlock (package:kernel/binary/ast_to_binary.dart:2196:5)
#42     Block.accept (package:kernel/ast.dart:9759:43)
#43     BinaryPrinter.writeNode (package:kernel/binary/ast_to_binary.dart:446:10)
#44     BinaryPrinter.writeOptionalNode (package:kernel/binary/ast_to_binary.dart:545:7)
#45     BinaryPrinter.visitFunctionNode (package:kernel/binary/ast_to_binary.dart:1559:5)
#46     FunctionNode.accept (package:kernel/ast.dart:4186:38)
#47     BinaryPrinter.writeFunctionNode (package:kernel/binary/ast_to_binary.dart:453:10)
#48     BinaryPrinter.visitProcedure (package:kernel/binary/ast_to_binary.dart:1388:5)
#49     Procedure.accept (package:kernel/ast.dart:3578:40)
#50     BinaryPrinter.writeProcedureNode (package:kernel/binary/ast_to_binary.dart:474:10)
#51     BinaryPrinter.writeProcedureNodeList (package:kernel/binary/ast_to_binary.dart:356:7)
#52     BinaryPrinter.visitLibrary (package:kernel/binary/ast_to_binary.dart:1132:5)
#53     Library.accept (package:kernel/ast.dart:585:38)
#54     BinaryPrinter.writeLibraryNode (package:kernel/binary/ast_to_binary.dart:467:10)
#55     BinaryPrinter.writeLibraries (package:kernel/binary/ast_to_binary.dart:780:9)
#56     BinaryPrinter.writeComponentFile.<anonymous closure> (package:kernel/binary/ast_to_binary.dart:619:7)
#57     Timeline.timeSync (dart:developer/timeline.dart:166:22)
#58     BinaryPrinter.writeComponentFile (package:kernel/binary/ast_to_binary.dart:600:14)
#59     serializeComponent (file:///C:/b/s/w/ir/x/w/sdk/pkg/vm/bin/kernel_service.dart:1036:11)
#60     _processLoadRequest (file:///C:/b/s/w/ir/x/w/sdk/pkg/vm/bin/kernel_service.dart:947:41)
<asynchronous suspension>

Dart version:

Dart SDK version: 3.0.0-272.0.dev (dev) (Fri Feb 24 15:27:56 2023 -0800) on "windows_x64"

If class Foo does not implement the Finalizable or the expression await bar() is stored in a variable:

  ...

  final result = await bar();
  for (final element in [result]) {
    print(element);
  }

... the program no longer crashes.

@lrhn lrhn added area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi labels Feb 26, 2023
@mraleph
Copy link
Member

mraleph commented Feb 27, 2023

/cc @dcharkes

@dcharkes dcharkes self-assigned this Feb 28, 2023
@dcharkes
Copy link
Contributor

dcharkes commented Mar 1, 2023

Thanks @halildurmus for the report!

I can reproduce this issue.

We have some strange interaction going on between the sync transformer and the Finalizable-transformer:

Block (Block({
  {
    Iterator<Foo> :sync-for-iterator = _GrowableList._literal1<Foo>(await block {
      final Future<Foo> :expressionValueWrappedFinalizable = bar();
      reachabilityFence(element);
    } => :expressionValueWrappedFinalizable).{Iterable.iterator};
    for (; :sync-for-iterator.{Iterator.moveNext}(); ) {
      final Foo element = :sync-for-iterator.{Iterator.current};
      {
        print(element);
        reachabilityFence(element);
      }
    }
  }
}))

We end up with a reachabilityFence of the element before the element is defined.

I'll investigate what the proper solution is.

@dcharkes
Copy link
Contributor

dcharkes commented Mar 1, 2023

Fix underway: https://dart-review.googlesource.com/c/sdk/+/286182

@halildurmus
Copy link
Contributor Author

Thank you, @dcharkes

@dcharkes
Copy link
Contributor

dcharkes commented Mar 1, 2023

More funny code:

import 'dart:ffi';

class Foo implements Finalizable {
  Foo? next;
}

Future<Foo> bar() => Future.value(Foo());

void main() async {
  for (Foo? element = await bar(); element != null; element = element.next) {
    print(element);
  }
}

But here it's actually correct to use element in the expressions inside the for definition. 😄

nielsenko added a commit to realm/realm-dart that referenced this issue Apr 24, 2024
This is to avoid a few Dart compiler bugs related to Finalizable objects:
- dart-lang/sdk#54414
- dart-lang/sdk#52596
- dart-lang/sdk#51538
nielsenko added a commit to realm/realm-dart that referenced this issue Apr 24, 2024
This is to avoid a few Dart compiler bugs related to Finalizable objects:
- dart-lang/sdk#54414
- dart-lang/sdk#52596
- dart-lang/sdk#51538
nielsenko added a commit to realm/realm-dart that referenced this issue Apr 24, 2024
* Bump required sdk version to ^3.3.0

This is to avoid a few Dart compiler bugs related to Finalizable objects:
- dart-lang/sdk#54414
- dart-lang/sdk#52596
- dart-lang/sdk#51538

* Update CHANGELOG
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. library-ffi
Projects
None yet
Development

No branches or pull requests

4 participants