Commit 9224d5d1 authored by bmeurer's avatar bmeurer Committed by Commit bot

[csa] Bailout to the runtime for ToInteger conversion in Array.p.indexOf.

The fast-path for Array.prototype.indexOf first checks whether the
receiver is a fast-mode JSArray (and there are no elements in the
prototype chain in case of holey arrays), then loads the known
JSArray::length, and afterwards calls ToInteger on the fromIndex.

But this ToInteger(fromIndex) call can cause arbitrary side effects if
the fromIndex is a JSReceiver, in particular it can invalidate the
assumptions about the fast-mode of the receiver and the length. In the
worst case this leads to OOB memory access.

Quick-fix is to bailout to the runtime if the fromIndex is neither a Smi
nor undefined, which represents the common cases.

R=jarin@chromium.org
BUG=chromium:702058

Review-Url: https://codereview.chromium.org/2756663002
Cr-Commit-Position: refs/heads/master@{#43843}
parent f76966ae
...@@ -2048,33 +2048,28 @@ TF_BUILTIN(ArrayIndexOf, CodeStubAssembler) { ...@@ -2048,33 +2048,28 @@ TF_BUILTIN(ArrayIndexOf, CodeStubAssembler) {
Bind(&init_k); Bind(&init_k);
{ {
Label done(this), init_k_smi(this), init_k_heap_num(this), // For now only deal with undefined and Smis here; we must be really careful
init_k_zero(this), init_k_n(this); // with side-effects from the ToInteger conversion as the side-effects might
Node* tagged_n = ToInteger(context, start_from); // render our assumptions about the receiver being a fast JSArray and the
// length invalid.
Branch(TaggedIsSmi(tagged_n), &init_k_smi, &init_k_heap_num); Label done(this), init_k_smi(this), init_k_other(this), init_k_zero(this),
init_k_n(this);
Branch(TaggedIsSmi(start_from), &init_k_smi, &init_k_other);
Bind(&init_k_smi); Bind(&init_k_smi);
{ {
start_from_var.Bind(SmiUntag(tagged_n)); // The fromIndex is a Smi.
start_from_var.Bind(SmiUntag(start_from));
Goto(&init_k_n); Goto(&init_k_n);
} }
Bind(&init_k_heap_num); Bind(&init_k_other);
{ {
Label do_return_not_found(this); // The fromIndex must be undefined then, otherwise bailout and let the
// This round is lossless for all valid lengths. // runtime deal with the full ToInteger conversion.
Node* fp_len = RoundIntPtrToFloat64(len_var.value()); GotoIfNot(IsUndefined(start_from), &call_runtime);
Node* fp_n = LoadHeapNumberValue(tagged_n); start_from_var.Bind(intptr_zero);
GotoIf(Float64GreaterThanOrEqual(fp_n, fp_len), &do_return_not_found);
start_from_var.Bind(ChangeInt32ToIntPtr(TruncateFloat64ToWord32(fp_n)));
Goto(&init_k_n); Goto(&init_k_n);
Bind(&do_return_not_found);
{
index_var.Bind(intptr_zero);
Goto(&return_not_found);
}
} }
Bind(&init_k_n); Bind(&init_k_n);
......
...@@ -2638,10 +2638,10 @@ class FastDoubleElementsAccessor ...@@ -2638,10 +2638,10 @@ class FastDoubleElementsAccessor
FixedArrayBase* elements_base = receiver->elements(); FixedArrayBase* elements_base = receiver->elements();
Object* value = *search_value; Object* value = *search_value;
if (start_from >= length) return Just<int64_t>(-1);
length = std::min(static_cast<uint32_t>(elements_base->length()), length); length = std::min(static_cast<uint32_t>(elements_base->length()), length);
if (start_from >= length) return Just<int64_t>(-1);
if (!value->IsNumber()) { if (!value->IsNumber()) {
return Just<int64_t>(-1); return Just<int64_t>(-1);
} }
......
// 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.
// Flags: --allow-natives-syntax
var arr = [];
for (var i = 0; i < 100000; i++) arr[i] = 0;
var fromIndex = {valueOf: function() { arr.length = 0; }};
arr.indexOf(1, fromIndex);
// 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.
// Flags: --allow-natives-syntax
var arr = [];
for (var i = 0; i < 100000; i++) arr[i] = 0.1;
var fromIndex = {valueOf: function() { arr.length = 0; }};
arr.indexOf(1.1, fromIndex);
// 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.
// Flags: --allow-natives-syntax
var arr = [];
for (var i = 0; i < 100000; i++) arr[i] = [];
var fromIndex = {valueOf: function() { arr.length = 0; }};
arr.indexOf({}, fromIndex);
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