Skip to content

Commit 0b3533a

Browse files
nshahanCommit Queue
authored and
Commit Queue
committed
[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: #49396 Fixes: #50602 Change-Id: Ief25fbe8c38330cca0c17be4d411780a20ab87a0 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/274729 Reviewed-by: Mark Zhou <[email protected]> Commit-Queue: Nicholas Shahan <[email protected]>
1 parent 3a1cc9f commit 0b3533a

File tree

2 files changed

+25
-2
lines changed

2 files changed

+25
-2
lines changed

pkg/dev_compiler/lib/src/kernel/compiler.dart

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6879,8 +6879,20 @@ class ProgramCompiler extends ComputeOnceConstantVisitor<js_ast.Expression>
68796879
}
68806880

68816881
@override
6882-
js_ast.Expression visitAwaitExpression(AwaitExpression node) =>
6883-
js_ast.Yield(_visitExpression(node.operand));
6882+
js_ast.Expression visitAwaitExpression(AwaitExpression node) {
6883+
var expression = _visitExpression(node.operand);
6884+
var type = node.runtimeCheckType;
6885+
if (type != null) {
6886+
// When an expected runtime type is present there is a possible soundness
6887+
// issue with the static types. The type of the await expression must be
6888+
// checked at runtime to ensure soundness.
6889+
var expectedType = _emitType(type);
6890+
var asyncLibrary = emitLibraryName(_coreTypes.asyncLibrary);
6891+
expression = js.call('#.awaitWithTypeCheck(#, #)',
6892+
[asyncLibrary, expectedType, expression]);
6893+
}
6894+
return js_ast.Yield(expression);
6895+
}
68846896

68856897
@override
68866898
js_ast.Expression visitFunctionExpression(FunctionExpression node) {

sdk/lib/_internal/js_dev_runtime/patch/async_patch.dart

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@ _async<T>(Function() initGenerator) {
129129
return asyncFuture;
130130
}
131131

132+
/// Checks that the value being awaited is a Future of the expected type and
133+
/// if not the value is wrapped in a new Future.
134+
///
135+
/// Calls to the method are generated from the compiler when it detects a type
136+
/// check is required on the expression in an await.
137+
///
138+
/// Closes a soundness hole where null could leak from an awaited Future.
139+
@JSExportName('awaitWithTypeCheck')
140+
_awaitWithTypeCheck<T>(Object? value) =>
141+
value is T ? value : _Future.value(value);
142+
132143
@patch
133144
class _AsyncRun {
134145
@patch

0 commit comments

Comments
 (0)