Commit 7dd261c3 authored by Daniel Clifford's avatar Daniel Clifford Committed by Commit Bot

Fix Array.protoype.slice bug in argument object handling

Bug: chromium:778574
Change-Id: I014b16b9deabab07ca7dfb662ea8cb0dbf9c8987
Reviewed-on: https://chromium-review.googlesource.com/738148
Commit-Queue: Daniel Clifford <danno@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48975}
parent d58b36b2
...@@ -48,28 +48,6 @@ inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) { ...@@ -48,28 +48,6 @@ inline bool ClampedToInteger(Isolate* isolate, Object* object, int* out) {
return false; return false;
} }
inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
int* out) {
Context* context = *isolate->native_context();
Map* map = object->map();
if (map != context->sloppy_arguments_map() &&
map != context->strict_arguments_map() &&
map != context->fast_aliased_arguments_map()) {
return false;
}
DCHECK(object->HasFastElements() || object->HasFastArgumentsElements());
Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
if (!len_obj->IsSmi()) return false;
*out = Max(0, Smi::ToInt(len_obj));
FixedArray* parameters = FixedArray::cast(object->elements());
if (object->HasSloppyArgumentsElements()) {
FixedArray* arguments = FixedArray::cast(parameters->get(1));
return *out <= arguments->length();
}
return *out <= parameters->length();
}
inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
JSArray* receiver) { JSArray* receiver) {
return JSObject::PrototypeHasNoElements(isolate, receiver); return JSObject::PrototypeHasNoElements(isolate, receiver);
...@@ -281,8 +259,8 @@ BUILTIN(ArraySlice) { ...@@ -281,8 +259,8 @@ BUILTIN(ArraySlice) {
} }
len = Smi::ToInt(array->length()); len = Smi::ToInt(array->length());
} else if (receiver->IsJSObject() && } else if (receiver->IsJSObject() &&
GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver), JSSloppyArgumentsObject::GetSloppyArgumentsLength(
&len)) { isolate, Handle<JSObject>::cast(receiver), &len)) {
// Array.prototype.slice.call(arguments, ...) is quite a common idiom // Array.prototype.slice.call(arguments, ...) is quite a common idiom
// (notably more than 50% of invocations in Web apps). // (notably more than 50% of invocations in Web apps).
// Treat it in C++ as well. // Treat it in C++ as well.
......
...@@ -45,6 +45,33 @@ void SloppyArgumentsElements::set_mapped_entry(uint32_t entry, Object* object) { ...@@ -45,6 +45,33 @@ void SloppyArgumentsElements::set_mapped_entry(uint32_t entry, Object* object) {
set(entry + kParameterMapStart, object); set(entry + kParameterMapStart, object);
} }
// TODO(danno): This shouldn't be inline here, but to defensively avoid
// regressions associated with the fix for the bug 778574, it's staying that way
// until the splice implementation in builtin-arrays.cc can be removed and this
// function can be moved into runtime-arrays.cc near its other usage.
bool JSSloppyArgumentsObject::GetSloppyArgumentsLength(Isolate* isolate,
Handle<JSObject> object,
int* out) {
Context* context = *isolate->native_context();
Map* map = object->map();
if (map != context->sloppy_arguments_map() &&
map != context->strict_arguments_map() &&
map != context->fast_aliased_arguments_map()) {
return false;
}
DCHECK(object->HasFastElements() || object->HasFastArgumentsElements());
Object* len_obj = object->InObjectPropertyAt(JSArgumentsObject::kLengthIndex);
if (!len_obj->IsSmi()) return false;
*out = Max(0, Smi::ToInt(len_obj));
FixedArray* parameters = FixedArray::cast(object->elements());
if (object->HasSloppyArgumentsElements()) {
FixedArray* arguments = FixedArray::cast(parameters->get(1));
return *out <= arguments->length();
}
return *out <= parameters->length();
}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
......
...@@ -42,6 +42,10 @@ class JSSloppyArgumentsObject : public JSArgumentsObject { ...@@ -42,6 +42,10 @@ class JSSloppyArgumentsObject : public JSArgumentsObject {
// Indices of in-object properties. // Indices of in-object properties.
static const int kCalleeIndex = kLengthIndex + 1; static const int kCalleeIndex = kLengthIndex + 1;
inline static bool GetSloppyArgumentsLength(Isolate* isolate,
Handle<JSObject> object,
int* out);
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSSloppyArgumentsObject); DISALLOW_IMPLICIT_CONSTRUCTORS(JSSloppyArgumentsObject);
}; };
......
...@@ -395,12 +395,11 @@ RUNTIME_FUNCTION(Runtime_TrySliceSimpleNonFastElements) { ...@@ -395,12 +395,11 @@ RUNTIME_FUNCTION(Runtime_TrySliceSimpleNonFastElements) {
return Smi::FromInt(0); return Smi::FromInt(0);
} }
} else { } else {
Map* map = receiver->map(); int len;
Context* context = *isolate->native_context(); if (!receiver->IsJSObject() ||
if (map != context->sloppy_arguments_map() && !JSSloppyArgumentsObject::GetSloppyArgumentsLength(
map != context->strict_arguments_map() && isolate, Handle<JSObject>::cast(receiver), &len) ||
map != context->fast_aliased_arguments_map() && (length > static_cast<uint32_t>(len))) {
map != context->slow_aliased_arguments_map()) {
return Smi::FromInt(0); return Smi::FromInt(0);
} }
} }
......
// Copyright 2017 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.
(function () {
arguments.length = 7;
Array.prototype.slice.call(arguments);
})();
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