mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 00:13:50 +00:00
[ddc] Fix unsound await expressions
Some expressions have a static type that can lead to a possible soundness issue when awaited. For those expressions an additional runtime check is performed. Issue: https://github.com/dart-lang/sdk/issues/49396 Fixes: https://github.com/dart-lang/sdk/issues/50602 Change-Id: Ief25fbe8c38330cca0c17be4d411780a20ab87a0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/274729 Reviewed-by: Mark Zhou <markzipan@google.com> Commit-Queue: Nicholas Shahan <nshahan@google.com>
This commit is contained in:
parent
3a1cc9faf6
commit
0b3533aa95
|
@ -6879,8 +6879,20 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
|
|||
}
|
||||
|
||||
@override
|
||||
js_ast.Expression visitAwaitExpression(AwaitExpression node) =>
|
||||
js_ast.Yield(_visitExpression(node.operand));
|
||||
js_ast.Expression visitAwaitExpression(AwaitExpression node) {
|
||||
var expression = _visitExpression(node.operand);
|
||||
var type = node.runtimeCheckType;
|
||||
if (type != null) {
|
||||
// When an expected runtime type is present there is a possible soundness
|
||||
// issue with the static types. The type of the await expression must be
|
||||
// checked at runtime to ensure soundness.
|
||||
var expectedType = _emitType(type);
|
||||
var asyncLibrary = emitLibraryName(_coreTypes.asyncLibrary);
|
||||
expression = js.call('#.awaitWithTypeCheck(#, #)',
|
||||
[asyncLibrary, expectedType, expression]);
|
||||
}
|
||||
return js_ast.Yield(expression);
|
||||
}
|
||||
|
||||
@override
|
||||
js_ast.Expression visitFunctionExpression(FunctionExpression node) {
|
||||
|
|
|
@ -129,6 +129,17 @@ _async<T>(Function() initGenerator) {
|
|||
return asyncFuture;
|
||||
}
|
||||
|
||||
/// Checks that the value being awaited is a Future of the expected type and
|
||||
/// if not the value is wrapped in a new Future.
|
||||
///
|
||||
/// Calls to the method are generated from the compiler when it detects a type
|
||||
/// check is required on the expression in an await.
|
||||
///
|
||||
/// Closes a soundness hole where null could leak from an awaited Future.
|
||||
@JSExportName('awaitWithTypeCheck')
|
||||
_awaitWithTypeCheck<T>(Object? value) =>
|
||||
value is T ? value : _Future.value(value);
|
||||
|
||||
@patch
|
||||
class _AsyncRun {
|
||||
@patch
|
||||
|
|
Loading…
Reference in a new issue