Commit 00a3bfac authored by Georg Neis's avatar Georg Neis Committed by Commit Bot

Check new length in array splice and unshift.

If the new length is too large, we must throw a TypeError.

Bug: v8:7652
Change-Id: I47268c04405f7a5f5bbc971cd434f2d786af9ca1
Reviewed-on: https://chromium-review.googlesource.com/1013563Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Georg Neis <neis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52624}
parent 2279dda6
...@@ -561,20 +561,24 @@ function ArrayUnshiftFallback(arg1) { // length == 1 ...@@ -561,20 +561,24 @@ function ArrayUnshiftFallback(arg1) { // length == 1
var len = TO_LENGTH(array.length); var len = TO_LENGTH(array.length);
var num_arguments = arguments.length; var num_arguments = arguments.length;
if (len > 0 && UseSparseVariant(array, len, IS_ARRAY(array), len) && const new_len = len + num_arguments;
!%object_is_sealed(array)) { if (num_arguments > 0) {
SparseMove(array, 0, 0, len, num_arguments); if (new_len >= 2**53) throw %make_type_error(kInvalidArrayLength);
} else {
SimpleMove(array, 0, 0, len, num_arguments);
}
for (var i = 0; i < num_arguments; i++) { if (len > 0 && UseSparseVariant(array, len, IS_ARRAY(array), len) &&
array[i] = arguments[i]; !%object_is_sealed(array)) {
SparseMove(array, 0, 0, len, num_arguments);
} else {
SimpleMove(array, 0, 0, len, num_arguments);
}
for (var i = 0; i < num_arguments; i++) {
array[i] = arguments[i];
}
} }
var new_length = len + num_arguments; array.length = new_len;
array.length = new_length; return new_len;
return new_length;
} }
...@@ -624,9 +628,14 @@ function ArraySpliceFallback(start, delete_count) { ...@@ -624,9 +628,14 @@ function ArraySpliceFallback(start, delete_count) {
var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len); var start_i = ComputeSpliceStartIndex(TO_INTEGER(start), len);
var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len, var del_count = ComputeSpliceDeleteCount(delete_count, num_arguments, len,
start_i); start_i);
var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
const new_len = len - del_count + num_elements_to_add;
if (new_len >= 2**53) throw %make_type_error(kInvalidArrayLength);
var deleted_elements = ArraySpeciesCreate(array, del_count); var deleted_elements = ArraySpeciesCreate(array, del_count);
deleted_elements.length = del_count; deleted_elements.length = del_count;
var num_elements_to_add = num_arguments > 2 ? num_arguments - 2 : 0;
if (del_count != num_elements_to_add && %object_is_sealed(array)) { if (del_count != num_elements_to_add && %object_is_sealed(array)) {
throw %make_type_error(kArrayFunctionsOnSealed); throw %make_type_error(kArrayFunctionsOnSealed);
...@@ -658,7 +667,7 @@ function ArraySpliceFallback(start, delete_count) { ...@@ -658,7 +667,7 @@ function ArraySpliceFallback(start, delete_count) {
while (arguments_index < arguments_length) { while (arguments_index < arguments_length) {
array[i++] = arguments[arguments_index++]; array[i++] = arguments[arguments_index++];
} }
array.length = len - del_count + num_elements_to_add; array.length = new_len;
// Return the deleted elements. // Return the deleted elements.
return deleted_elements; return deleted_elements;
......
// 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.
let a = {length: 2**53 - 1};
const unshift = Array.prototype.unshift;
assertThrows(() => unshift.call(a, 42), TypeError);
assertEquals(unshift.call(a), 2**53 - 1);
const splice = Array.prototype.splice;
assertThrows(() => splice.call(a, 0, 0, 42), TypeError);
assertEquals(splice.call(a, 0, 1, 42).length, 1);
assertEquals(a[0], 42);
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