Commit aaa78c33 authored by Peter Marshall's avatar Peter Marshall Committed by Commit Bot

[typedarray] Fix IterableToList when Number has an iterator

IterableToListCanBeElided checked that the input was always a HeapObject
but this is not true when an iterator symbol is defined on the Number
prototype, meaning Smi and HeapNumber can also be passed in.

Added a regression test for the crash and some correctness tests for
smi and double input to TA.from.

Also factored out the tests in typedarray-from.js that modify global
state e.g. protector cells, so that one iteration of the top level
loop does not interfere with the next.

Bug: chromium:814643
Change-Id: I364d11f011faf8370446f905a35a945d47e4477f
Reviewed-on: https://chromium-review.googlesource.com/930962Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Peter Marshall <petermarshall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51461}
parent ef930261
...@@ -1247,9 +1247,13 @@ RUNTIME_FUNCTION(Runtime_CreateDataProperty) { ...@@ -1247,9 +1247,13 @@ RUNTIME_FUNCTION(Runtime_CreateDataProperty) {
RUNTIME_FUNCTION(Runtime_IterableToListCanBeElided) { RUNTIME_FUNCTION(Runtime_IterableToListCanBeElided) {
HandleScope scope(isolate); HandleScope scope(isolate);
DCHECK_EQ(1, args.length()); DCHECK_EQ(1, args.length());
CONVERT_ARG_HANDLE_CHECKED(HeapObject, obj, 0); CONVERT_ARG_HANDLE_CHECKED(Object, obj, 0);
if (!obj->IsJSObject()) return isolate->heap()->ToBoolean(false); // If an iterator symbol is added to the Number prototype, we could see a Smi.
if (obj->IsSmi()) return isolate->heap()->ToBoolean(false);
if (!HeapObject::cast(*obj)->IsJSObject()) {
return isolate->heap()->ToBoolean(false);
}
// While iteration alone may not have observable side-effects, calling // While iteration alone may not have observable side-effects, calling
// toNumber on an object will. Make sure the arg is not an array of objects. // toNumber on an object will. Make sure the arg is not an array of objects.
......
...@@ -151,14 +151,6 @@ for (var constructor of typedArrayConstructors) { ...@@ -151,14 +151,6 @@ for (var constructor of typedArrayConstructors) {
assertThrows(function() { constructor.from([], 'noncallable'); }, assertThrows(function() { constructor.from([], 'noncallable'); },
TypeError); TypeError);
source = [1, 2, 3];
source[Symbol.iterator] = undefined;
assertArrayLikeEquals(constructor.from(source), source, constructor);
source = [{ valueOf: function(){ return 42; }}];
source[Symbol.iterator] = undefined;
assertArrayLikeEquals(constructor.from(source), [42], constructor);
source = [1, 2, 3]; source = [1, 2, 3];
var proxy = new Proxy(source, {}); var proxy = new Proxy(source, {});
assertArrayLikeEquals(constructor.from(proxy), source, constructor); assertArrayLikeEquals(constructor.from(proxy), source, constructor);
...@@ -171,6 +163,26 @@ for (var constructor of typedArrayConstructors) { ...@@ -171,6 +163,26 @@ for (var constructor of typedArrayConstructors) {
} }
}); });
assertArrayLikeEquals(constructor.from(proxy), [2, 3, 4], constructor); assertArrayLikeEquals(constructor.from(proxy), [2, 3, 4], constructor);
}
// Tests that modify global state in a way that affects fast paths e.g. by
// invalidating protectors or changing prototypes.
for (var constructor of typedArrayConstructors) {
source = [1, 2, 3];
source[Symbol.iterator] = undefined;
assertArrayLikeEquals(constructor.from(source), source, constructor);
source = [{ valueOf: function(){ return 42; }}];
source[Symbol.iterator] = undefined;
assertArrayLikeEquals(constructor.from(source), [42], constructor);
Number.prototype[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
}
assertArrayLikeEquals(constructor.from(1), [1, 2, 3], constructor);
assertArrayLikeEquals(constructor.from(1.1), [1, 2, 3], constructor);
var nullIterator = {}; var nullIterator = {};
nullIterator[Symbol.iterator] = null; nullIterator[Symbol.iterator] = null;
......
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Number.prototype.__proto__ = String.prototype;
Uint8Array.from(1);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment