Commit 1444bebe authored by Jakob Gruber's avatar Jakob Gruber Committed by Commit Bot

[array] Weaken bounds checks in Array.p.sort

The array length is modifiable by user code that is called as a
side-effect during the sorting algorithm. We thus cannot base any
guarantees on the current length, but must reference the initially-read
array length instead.

Note that even though the algorithm may read and write from beyond
the current array length value, this adheres to the spec, which only
requires accesses to be within the original array dimensions (i.e.: 0
<= i < original array length).

Bug: chromium:901633
Change-Id: Id765e80d4231ff6f2a73e040ec94c2b07f8c5b0f
Reviewed-on: https://chromium-review.googlesource.com/c/1317814
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: 's avatarDaniel Clifford <danno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#57279}
parent f5203615
// 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.
const magic0 = 2396;
const magic1 = 1972;
// Fill xs with float arrays.
const xs = [];
for (let j = 0; j < magic0; ++j) {
xs[j] = [j + 0.1];
}
// Sort, but trim the array at some point.
let cmp_calls = 0;
xs.sort((lhs, rhs) => {
lhs = lhs || [0];
rhs = rhs || [0];
if (cmp_calls++ == magic1) xs.length = 1;
return lhs[0] - rhs[0];
});
// The final shape of the array is unspecified since the comparison function is
// inconsistent.
...@@ -360,8 +360,7 @@ module array { ...@@ -360,8 +360,7 @@ module array {
const receiver: JSReceiver = GetReceiver(sortState); const receiver: JSReceiver = GetReceiver(sortState);
const initialReceiverMap: Object = sortState[kInitialReceiverMapIdx]; const initialReceiverMap: Object = sortState[kInitialReceiverMapIdx];
const initialReceiverLength: Number = const initialReceiverLength: Number = GetInitialReceiverLength(sortState);
UnsafeCast<Number>(sortState[kInitialReceiverLengthIdx]);
const canUseSameAccessorFn: CanUseSameAccessorFn = const canUseSameAccessorFn: CanUseSameAccessorFn =
GetCanUseSameAccessorFn(sortState); GetCanUseSameAccessorFn(sortState);
...@@ -384,6 +383,10 @@ module array { ...@@ -384,6 +383,10 @@ module array {
return object.elements; return object.elements;
} }
macro GetInitialReceiverLength(sortState: FixedArray): Number {
return UnsafeCast<Number>(sortState[kInitialReceiverLengthIdx]);
}
macro GetLoadFn(sortState: FixedArray): LoadFn { macro GetLoadFn(sortState: FixedArray): LoadFn {
return UnsafeCast<LoadFn>(sortState[kLoadFnIdx]); return UnsafeCast<LoadFn>(sortState[kLoadFnIdx]);
} }
...@@ -543,12 +546,6 @@ module array { ...@@ -543,12 +546,6 @@ module array {
EnsureSuccess(sortState) otherwise Bailout; EnsureSuccess(sortState) otherwise Bailout;
} }
// Used for OOB asserts in Copy* builtins.
transitioning macro GetReceiverLengthFromSortState(implicit context: Context)(
sortState: FixedArray): Number {
return GetLengthProperty(GetReceiver(sortState));
}
transitioning macro CopyToTempArray( transitioning macro CopyToTempArray(
context: Context, sortState: FixedArray, load: LoadFn, context: Context, sortState: FixedArray, load: LoadFn,
srcElements: HeapObject, srcPos: Smi, tempArray: FixedArray, dstPos: Smi, srcElements: HeapObject, srcPos: Smi, tempArray: FixedArray, dstPos: Smi,
...@@ -556,7 +553,7 @@ module array { ...@@ -556,7 +553,7 @@ module array {
labels Bailout { labels Bailout {
assert(srcPos >= 0); assert(srcPos >= 0);
assert(dstPos >= 0); assert(dstPos >= 0);
assert(srcPos <= GetReceiverLengthFromSortState(sortState) - length); assert(srcPos <= GetInitialReceiverLength(sortState) - length);
assert(dstPos <= tempArray.length - length); assert(dstPos <= tempArray.length - length);
let srcIdx: Smi = srcPos; let srcIdx: Smi = srcPos;
...@@ -577,7 +574,7 @@ module array { ...@@ -577,7 +574,7 @@ module array {
assert(srcPos >= 0); assert(srcPos >= 0);
assert(dstPos >= 0); assert(dstPos >= 0);
assert(srcPos <= tempArray.length - length); assert(srcPos <= tempArray.length - length);
assert(dstPos <= GetReceiverLengthFromSortState(sortState) - length); assert(dstPos <= GetInitialReceiverLength(sortState) - length);
let store: StoreFn = GetStoreFn(sortState); let store: StoreFn = GetStoreFn(sortState);
...@@ -603,8 +600,8 @@ module array { ...@@ -603,8 +600,8 @@ module array {
srcPos: Smi, dstPos: Smi, length: Smi): Smi { srcPos: Smi, dstPos: Smi, length: Smi): Smi {
assert(srcPos >= 0); assert(srcPos >= 0);
assert(dstPos >= 0); assert(dstPos >= 0);
assert(srcPos <= GetReceiverLengthFromSortState(sortState) - length); assert(srcPos <= GetInitialReceiverLength(sortState) - length);
assert(dstPos <= GetReceiverLengthFromSortState(sortState) - length); assert(dstPos <= GetInitialReceiverLength(sortState) - length);
try { try {
let load: LoadFn = GetLoadFn(sortState); let load: LoadFn = GetLoadFn(sortState);
......
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