[builtins] Fix FastCreateDataProperty

... which didn't check writability of array length on appending
a new element to an array.

Bug: chromium:1041251
Change-Id: I6935e505a4844e5b22abe9d4a42786619499daa6
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2023551
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#66023}
This commit is contained in:
Igor Sheludko 2020-01-28 12:24:45 +01:00 committed by Commit Bot
parent 390c7fed66
commit 68cc5c6796
2 changed files with 42 additions and 20 deletions

View File

@ -1439,36 +1439,44 @@ transitioning builtin FastCreateDataProperty(implicit context: Context)(
const array = Cast<FastJSArray>(receiver) otherwise Slow;
const index: Smi = Cast<Smi>(key) otherwise goto Slow;
if (index < 0 || index > array.length) goto Slow;
array::EnsureWriteableFastElements(array);
const isAppend = index == array.length;
const kind = array.map.elements_kind;
// We may have to transition a.
// For now, if transition is required, jump away to slow.
if (IsFastSmiElementsKind(kind)) {
const smiValue = Cast<Smi>(value) otherwise Slow;
if (isAppend) {
if (isAppend) {
// Fast append only works on fast elements kind and with writable length.
const kind = EnsureArrayPushable(array.map) otherwise Slow;
array::EnsureWriteableFastElements(array);
// We may have to transition a.
// For now, if transition is required, jump away to slow.
if (IsFastSmiElementsKind(kind)) {
BuildAppendJSArray(ElementsKind::HOLEY_SMI_ELEMENTS, array, value)
otherwise Slow;
} else {
const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
elements[index] = smiValue;
}
} else if (IsDoubleElementsKind(kind)) {
const numberValue = Cast<Number>(value) otherwise Slow;
if (isAppend) {
} else if (IsDoubleElementsKind(kind)) {
BuildAppendJSArray(ElementsKind::HOLEY_DOUBLE_ELEMENTS, array, value)
otherwise Slow;
} else {
assert(IsFastSmiOrTaggedElementsKind(kind));
BuildAppendJSArray(ElementsKind::HOLEY_ELEMENTS, array, value)
otherwise Slow;
}
} else {
// Non-appending element store.
const kind = array.map.elements_kind;
array::EnsureWriteableFastElements(array);
// We may have to transition a.
// For now, if transition is required, jump away to slow.
if (IsFastSmiElementsKind(kind)) {
const smiValue = Cast<Smi>(value) otherwise Slow;
const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
elements[index] = smiValue;
} else if (IsDoubleElementsKind(kind)) {
const numberValue = Cast<Number>(value) otherwise Slow;
const doubleElements = Cast<FixedDoubleArray>(array.elements)
otherwise unreachable;
doubleElements[index] = numberValue;
}
} else {
assert(IsFastSmiOrTaggedElementsKind(kind));
if (isAppend) {
BuildAppendJSArray(ElementsKind::HOLEY_ELEMENTS, array, value)
otherwise Slow;
} else {
assert(IsFastSmiOrTaggedElementsKind(kind));
const elements = Cast<FixedArray>(array.elements) otherwise unreachable;
elements[index] = value;
}

View File

@ -0,0 +1,14 @@
// Copyright 2020 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 v0 = [0, 1];
v0.constructor = {
[Symbol.species]: function() {
let v1 = [2];
Object.defineProperty(v1, "length", {writable: false});
return v1;
}
}
assertThrows(() => Array.prototype.map.call(v0, function() {}), TypeError);