Commit 75e04cd2 authored by Igor Sheludko's avatar Igor Sheludko Committed by Commit Bot

[builtins] Throw on pop()/shift() when JSArray's length is not writable.

Bug: chromium:823069
Change-Id: Ie5be40da1e64a11c7a3c6ba5d2bc193bd78ca737
Reviewed-on: https://chromium-review.googlesource.com/1002560Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/master@{#52508}
parent f9caff46
...@@ -1605,6 +1605,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object, ...@@ -1605,6 +1605,7 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
PropertyAttributes attribs = static_cast<PropertyAttributes>( PropertyAttributes attribs = static_cast<PropertyAttributes>(
DONT_ENUM | DONT_DELETE); DONT_ENUM | DONT_DELETE);
STATIC_ASSERT(JSArray::kLengthDescriptorIndex == 0);
{ // Add length. { // Add length.
Descriptor d = Descriptor::AccessorConstant( Descriptor d = Descriptor::AccessorConstant(
factory->length_string(), factory->array_length_accessor(), attribs); factory->length_string(), factory->array_length_accessor(), attribs);
......
...@@ -2244,14 +2244,28 @@ Node* CodeStubAssembler::StoreFeedbackVectorSlot(Node* object, ...@@ -2244,14 +2244,28 @@ Node* CodeStubAssembler::StoreFeedbackVectorSlot(Node* object,
} }
} }
void CodeStubAssembler::EnsureArrayLengthWritable(Node* map, Label* bailout) { void CodeStubAssembler::EnsureArrayLengthWritable(TNode<Map> map,
Label* bailout) {
// Don't support arrays in dictionary named property mode.
GotoIf(IsDictionaryMap(map), bailout);
// Check whether the length property is writable. The length property is the // Check whether the length property is writable. The length property is the
// only default named property on arrays. It's nonconfigurable, hence is // only default named property on arrays. It's nonconfigurable, hence is
// guaranteed to stay the first property. // guaranteed to stay the first property.
Node* descriptors = LoadMapDescriptors(map); TNode<DescriptorArray> descriptors = LoadMapDescriptors(map);
Node* details =
LoadFixedArrayElement(descriptors, DescriptorArray::ToDetailsIndex(0)); int length_index = JSArray::kLengthDescriptorIndex;
GotoIf(IsSetSmi(details, PropertyDetails::kAttributesReadOnlyMask), bailout); #ifdef DEBUG
TNode<Name> maybe_length = CAST(LoadFixedArrayElement(
descriptors, DescriptorArray::ToKeyIndex(length_index)));
CSA_ASSERT(this,
WordEqual(maybe_length, LoadRoot(Heap::klength_stringRootIndex)));
#endif
TNode<Int32T> details = LoadAndUntagToWord32FixedArrayElement(
descriptors, DescriptorArray::ToDetailsIndex(length_index));
GotoIf(IsSetWord32(details, PropertyDetails::kAttributesReadOnlyMask),
bailout);
} }
TNode<Int32T> CodeStubAssembler::EnsureArrayPushable(TNode<Map> map, TNode<Int32T> CodeStubAssembler::EnsureArrayPushable(TNode<Map> map,
...@@ -2265,11 +2279,6 @@ TNode<Int32T> CodeStubAssembler::EnsureArrayPushable(TNode<Map> map, ...@@ -2265,11 +2279,6 @@ TNode<Int32T> CodeStubAssembler::EnsureArrayPushable(TNode<Map> map,
GotoIf(Word32NotEqual(test, Int32Constant(Map::IsExtensibleBit::kMask)), GotoIf(Word32NotEqual(test, Int32Constant(Map::IsExtensibleBit::kMask)),
bailout); bailout);
// Disallow pushing onto arrays in dictionary named property mode. We need
// to figure out whether the length property is still writable.
Comment("Disallow pushing onto arrays in dictionary named property mode");
GotoIf(IsDictionaryMap(map), bailout);
EnsureArrayLengthWritable(map, bailout); EnsureArrayLengthWritable(map, bailout);
TNode<Uint32T> kind = DecodeWord32<Map::ElementsKindBits>(bit_field2); TNode<Uint32T> kind = DecodeWord32<Map::ElementsKindBits>(bit_field2);
......
...@@ -778,7 +778,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler { ...@@ -778,7 +778,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
int additional_offset = 0, int additional_offset = 0,
ParameterMode parameter_mode = INTPTR_PARAMETERS); ParameterMode parameter_mode = INTPTR_PARAMETERS);
void EnsureArrayLengthWritable(Node* map, Label* bailout); void EnsureArrayLengthWritable(TNode<Map> map, Label* bailout);
// EnsureArrayPushable verifies that receiver with this map is: // EnsureArrayPushable verifies that receiver with this map is:
// 1. Is not a prototype. // 1. Is not a prototype.
......
...@@ -81,6 +81,8 @@ class JSArray : public JSObject { ...@@ -81,6 +81,8 @@ class JSArray : public JSObject {
static const int kLengthOffset = JSObject::kHeaderSize; static const int kLengthOffset = JSObject::kHeaderSize;
static const int kSize = kLengthOffset + kPointerSize; static const int kSize = kLengthOffset + kPointerSize;
static const int kLengthDescriptorIndex = 0;
// Max. number of elements being copied in Array builtins. // Max. number of elements being copied in Array builtins.
static const int kMaxCopyElements = 100; static const int kMaxCopyElements = 100;
......
// 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.
var v = [];
Object.defineProperty(v, "length", {value: 3, writable: false});
assertThrows(()=>{v.pop();});
assertThrows(()=>{v.shift();});
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