From eb6b474d7a8c0d34b536a803f9752b9429629259 Mon Sep 17 00:00:00 2001 From: "Lasse R.H. Nielsen" Date: Mon, 1 Mar 2021 13:56:19 +0000 Subject: [PATCH] Fix null-safety issue in VM's typed-data + operators. Fixes #45140. Bug: http://dartbug.com/45140 Change-Id: I95f45c64d86428ddb67d176cdd2d50cfdbadfe8b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/188283 Reviewed-by: Martin Kustermann Commit-Queue: Lasse R.H. Nielsen --- .../_internal/vm/lib/typed_data_patch.dart | 40 ++---------- .../lib/typed_data/regression_45140_test.dart | 63 +++++++++++++++++++ 2 files changed, 68 insertions(+), 35 deletions(-) create mode 100644 tests/lib/typed_data/regression_45140_test.dart diff --git a/sdk/lib/_internal/vm/lib/typed_data_patch.dart b/sdk/lib/_internal/vm/lib/typed_data_patch.dart index d608ab6926f2..b0c18d546f49 100644 --- a/sdk/lib/_internal/vm/lib/typed_data_patch.dart +++ b/sdk/lib/_internal/vm/lib/typed_data_patch.dart @@ -150,13 +150,7 @@ mixin _IntListMixin implements List { return -1; } - List operator +(List other) { - int totalLength = this.length + other.length; - return [] - ..length = totalLength - ..setRange(0, this.length, this) - ..setRange(this.length, totalLength, other); - } + List operator +(List other) => [...this, ...other]; bool contains(Object? element) { var len = this.length; @@ -506,13 +500,7 @@ mixin _DoubleListMixin implements List { return -1; } - List operator +(List other) { - int totalLength = this.length + other.length; - return [] - ..length = totalLength - ..setRange(0, this.length, this) - ..setRange(this.length, totalLength, other); - } + List operator +(List other) => [...this, ...other]; bool contains(Object? element) { var len = this.length; @@ -868,13 +856,7 @@ abstract class _Float32x4ListMixin implements List { return -1; } - List operator +(List other) { - int totalLength = this.length + other.length; - return [] - ..length = totalLength - ..setRange(0, this.length, this) - ..setRange(this.length, totalLength, other); - } + List operator +(List other) => [...this, ...other]; bool contains(Object? element) { var len = this.length; @@ -1228,13 +1210,7 @@ abstract class _Int32x4ListMixin implements List { return -1; } - List operator +(List other) { - int totalLength = this.length + other.length; - return [] - ..length = totalLength - ..setRange(0, this.length, this) - ..setRange(this.length, totalLength, other); - } + List operator +(List other) => [...this, ...other]; bool contains(Object? element) { var len = this.length; @@ -1587,13 +1563,7 @@ abstract class _Float64x2ListMixin implements List { return -1; } - List operator +(List other) { - int totalLength = this.length + other.length; - return [] - ..length = totalLength - ..setRange(0, this.length, this) - ..setRange(this.length, totalLength, other); - } + List operator +(List other) => [...this, ...other]; bool contains(Object? element) { var len = this.length; diff --git a/tests/lib/typed_data/regression_45140_test.dart b/tests/lib/typed_data/regression_45140_test.dart new file mode 100644 index 000000000000..864ce4523c24 --- /dev/null +++ b/tests/lib/typed_data/regression_45140_test.dart @@ -0,0 +1,63 @@ +// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:math' show Random; +import 'dart:typed_data'; +import 'package:expect/expect.dart'; + +void main() { + var r = Random(); + int genInt() => r.nextInt(256); + double genDbl() => r.nextDouble(); + Int32x4 genIx4() => Int32x4(genInt(), genInt(), genInt(), genInt()); + Float32x4 genFx4() => Float32x4(genDbl(), genDbl(), genDbl(), genDbl()); + Float64x2 genDx2() => Float64x2(genDbl(), genDbl()); + + test("Uint8List", (n) => Uint8List(n)..fill(genInt)); + test("Uint16List", (n) => Uint16List(n)..fill(genInt)); + test("Uint32List", (n) => Uint32List(n)..fill(genInt)); + test("Int8List", (n) => Int8List(n)..fill(genInt)); + test("Int16List", (n) => Int16List(n)..fill(genInt)); + test("Int32List", (n) => Int32List(n)..fill(genInt)); + test("Uint8ClampedList", (n) => Uint8ClampedList(n)..fill(genInt)); + test("Float32List", (n) => Float32List(n)..fill(genDbl)); + test("Float64List", (n) => Float64List(n)..fill(genDbl)); + test("Int32x4List", (n) => Int32x4List(n)..fill(genIx4)); + test("Float32x4List", (n) => Float32x4List(n)..fill(genFx4)); + test("Float64x2List", (n) => Float64x2List(n)..fill(genDx2)); +} + +void test(String name, List create(int n)) { + var l1 = create(17); + var l2 = create(13); + List l3; + try { + // Shouldn't throw: + l3 = l1 + l2; + } catch (e) { + // Until we change Expect.fail to return Never. + Expect.fail("$name: $e") as Never; + } + Expect.equals(30, l3.length); + if (0 is T || 0.0 is T) { + // Int32x4 etc. do not support `==`. + Expect.listEquals(l1, l3.sublist(0, 17), "$name first"); + Expect.listEquals(l2, l3.sublist(17), "$name second"); + } + // Result is growable, shouldn't throw. + try { + l3.add(l3.first); + } catch (e) { + Expect.fail("$name: $e"); + } +} + +// Fill a list with (random) generated values. +extension on List { + void fill(T gen()) { + for (var i = 0; i < length; i++) { + this[i] = gen(); + } + } +}