Commit e33b6881 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Fix Array.prototype.concat when exceeding array size limit.

R=verwaest@chromium.org
BUG=v8:581

Review URL: https://chromiumcodereview.appspot.com/13465008

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14154 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 1141d4af
......@@ -8862,14 +8862,18 @@ class ArrayConcatVisitor {
storage_(Handle<FixedArray>::cast(
isolate->global_handles()->Create(*storage))),
index_offset_(0u),
fast_elements_(fast_elements) { }
fast_elements_(fast_elements),
exceeds_array_limit_(false) { }
~ArrayConcatVisitor() {
clear_storage();
}
void visit(uint32_t i, Handle<Object> elm) {
if (i >= JSObject::kMaxElementCount - index_offset_) return;
if (i > JSObject::kMaxElementCount - index_offset_) {
exceeds_array_limit_ = true;
return;
}
uint32_t index = index_offset_ + i;
if (fast_elements_) {
......@@ -8904,6 +8908,10 @@ class ArrayConcatVisitor {
}
}
bool exceeds_array_limit() {
return exceeds_array_limit_;
}
Handle<JSArray> ToArray() {
Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
Handle<Object> length =
......@@ -8962,7 +8970,8 @@ class ArrayConcatVisitor {
// Index after last seen index. Always less than or equal to
// JSObject::kMaxElementCount.
uint32_t index_offset_;
bool fast_elements_;
bool fast_elements_ : 1;
bool exceeds_array_limit_ : 1;
};
......@@ -9518,6 +9527,11 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ArrayConcat) {
}
}
if (visitor.exceeds_array_limit()) {
return isolate->Throw(
*isolate->factory()->NewRangeError("invalid_array_length",
HandleVector<Object>(NULL, 0)));
}
return *visitor.ToArray();
}
......
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
var pow30 = Math.pow(2, 30);
var pow31 = Math.pow(2, 31);
var a = [];
a[pow31] = 31;
assertEquals(pow31 + 1, a.length);
assertThrows(function() { a.concat(a); }, RangeError);
var b = [];
b[pow31 - 2] = 32;
var ab = a.concat(b);
assertEquals(2 * pow31 - 1, ab.length);
assertEquals(31, ab[pow31]);
assertEquals(32, ab[2 * pow31 - 1]);
var c = [];
c[pow30] = 30;
assertThrows(function() { c.concat(c, a); }, RangeError);
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