Commit b5da57a0 authored by Dan Elphick's avatar Dan Elphick Committed by Commit Bot

[builtins] Fix OOB read/write using Array.from

Always use the runtime to set the length on an array if it doesn't match
the expected length after populating it using Array.from.

Bug: chromium:821137
Change-Id: I5a730db58de61ba789040e6dfc815d6067fbae64
Reviewed-on: https://chromium-review.googlesource.com/962222Reviewed-by: 's avatarJakob Gruber <jgruber@chromium.org>
Commit-Queue: Dan Elphick <delphick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51919}
parent 1dab065b
......@@ -1945,10 +1945,13 @@ class ArrayPopulatorAssembler : public CodeStubAssembler {
void GenerateSetLength(TNode<Context> context, TNode<Object> array,
TNode<Number> length) {
Label fast(this), runtime(this), done(this);
// TODO(delphick): We should be able to skip the fast set altogether, if the
// length already equals the expected length, which it always is now on the
// fast path.
// Only set the length in this stub if
// 1) the array has fast elements,
// 2) the length is writable,
// 3) the new length is greater than or equal to the old length.
// 3) the new length is equal to the old length.
// 1) Check that the array has fast elements.
// TODO(delphick): Consider changing this since it does an an unnecessary
......@@ -1970,10 +1973,10 @@ class ArrayPopulatorAssembler : public CodeStubAssembler {
// BranchIfFastJSArray above.
EnsureArrayLengthWritable(LoadMap(fast_array), &runtime);
// 3) If the created array already has a length greater than required,
// 3) If the created array's length does not match the required length,
// then use the runtime to set the property as that will insert holes
// into the excess elements and/or shrink the backing store.
GotoIf(SmiLessThan(length_smi, old_length), &runtime);
// into excess elements or shrink the backing store as appropriate.
GotoIf(SmiNotEqual(length_smi, old_length), &runtime);
StoreObjectFieldNoWriteBarrier(fast_array, JSArray::kLengthOffset,
length_smi);
......
// 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.
// Tests that creating an iterator that shrinks the array populated by
// Array.from does not lead to out of bounds writes.
let oobArray = [];
let maxSize = 1028 * 8;
Array.from.call(function() { return oobArray }, {[Symbol.iterator] : _ => (
{
counter : 0,
next() {
let result = this.counter++;
if (this.counter > maxSize) {
oobArray.length = 0;
return {done: true};
} else {
return {value: result, done: false};
}
}
}
) });
assertEquals(oobArray.length, maxSize);
// iterator reset the length to 0 just before returning done, so this will crash
// if the backing store was not resized correctly.
oobArray[oobArray.length - 1] = 0x41414141;
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