Skip to content

Commit

Permalink
Fix null-safety issue in VM's typed-data + operators.
Browse files Browse the repository at this point in the history
Fixes #45140.

Bug: http://dartbug.com/45140
Change-Id: I95f45c64d86428ddb67d176cdd2d50cfdbadfe8b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/188283
Reviewed-by: Martin Kustermann <[email protected]>
Commit-Queue: Lasse R.H. Nielsen <[email protected]>
  • Loading branch information
lrhn authored and [email protected] committed Mar 1, 2021
1 parent be8196b commit eb6b474
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 35 deletions.
40 changes: 5 additions & 35 deletions sdk/lib/_internal/vm/lib/typed_data_patch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,7 @@ mixin _IntListMixin implements List<int> {
return -1;
}

List<int> operator +(List<int> other) {
int totalLength = this.length + other.length;
return <int>[]
..length = totalLength
..setRange(0, this.length, this)
..setRange(this.length, totalLength, other);
}
List<int> operator +(List<int> other) => [...this, ...other];

bool contains(Object? element) {
var len = this.length;
Expand Down Expand Up @@ -506,13 +500,7 @@ mixin _DoubleListMixin implements List<double> {
return -1;
}

List<double> operator +(List<double> other) {
int totalLength = this.length + other.length;
return <double>[]
..length = totalLength
..setRange(0, this.length, this)
..setRange(this.length, totalLength, other);
}
List<double> operator +(List<double> other) => [...this, ...other];

bool contains(Object? element) {
var len = this.length;
Expand Down Expand Up @@ -868,13 +856,7 @@ abstract class _Float32x4ListMixin implements List<Float32x4> {
return -1;
}

List<Float32x4> operator +(List<Float32x4> other) {
int totalLength = this.length + other.length;
return <Float32x4>[]
..length = totalLength
..setRange(0, this.length, this)
..setRange(this.length, totalLength, other);
}
List<Float32x4> operator +(List<Float32x4> other) => [...this, ...other];

bool contains(Object? element) {
var len = this.length;
Expand Down Expand Up @@ -1228,13 +1210,7 @@ abstract class _Int32x4ListMixin implements List<Int32x4> {
return -1;
}

List<Int32x4> operator +(List<Int32x4> other) {
int totalLength = this.length + other.length;
return <Int32x4>[]
..length = totalLength
..setRange(0, this.length, this)
..setRange(this.length, totalLength, other);
}
List<Int32x4> operator +(List<Int32x4> other) => [...this, ...other];

bool contains(Object? element) {
var len = this.length;
Expand Down Expand Up @@ -1587,13 +1563,7 @@ abstract class _Float64x2ListMixin implements List<Float64x2> {
return -1;
}

List<Float64x2> operator +(List<Float64x2> other) {
int totalLength = this.length + other.length;
return <Float64x2>[]
..length = totalLength
..setRange(0, this.length, this)
..setRange(this.length, totalLength, other);
}
List<Float64x2> operator +(List<Float64x2> other) => [...this, ...other];

bool contains(Object? element) {
var len = this.length;
Expand Down
63 changes: 63 additions & 0 deletions tests/lib/typed_data/regression_45140_test.dart
Original file line number Diff line number Diff line change
@@ -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<T>(String name, List<T> create(int n)) {
var l1 = create(17);
var l2 = create(13);
List<T> 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<T> on List<T> {
void fill(T gen()) {
for (var i = 0; i < length; i++) {
this[i] = gen();
}
}
}

0 comments on commit eb6b474

Please sign in to comment.