Reviewers: adamk,

Description:
Fix Array.prototype.concat for arguments object with getter.

R=ad...@chromium.org
BUG=crbug:516775
LOG=N

Please review this at https://codereview.chromium.org/1270403002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+35, -7 lines):
  M src/runtime/runtime-array.cc
  A test/mjsunit/regress/regress-crbug-516775.js


Index: src/runtime/runtime-array.cc
diff --git a/src/runtime/runtime-array.cc b/src/runtime/runtime-array.cc
index b5655db611a5ce34161d45990718872fa7f02916..4f8bc05cb6e43d9e36506bab216fc991a702992c 100644
--- a/src/runtime/runtime-array.cc
+++ b/src/runtime/runtime-array.cc
@@ -362,7 +362,8 @@ static int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
 }


-static void CollectElementIndices(Handle<JSObject> object, uint32_t range,
+// Return false on exception.
+static bool CollectElementIndices(Handle<JSObject> object, uint32_t range,
                                   List<uint32_t>* indices) {
   Isolate* isolate = object->GetIsolate();
   ElementsKind kind = object->GetElementsKind();
@@ -432,14 +433,20 @@ static void CollectElementIndices(Handle<JSObject> object, uint32_t range,
         for (uint32_t i = 0; i < length; i++) {
           indices->Add(i);
         }
-        if (length == range) return;  // All indices accounted for already.
+ if (length == range) return true; // All indices accounted for already.
         break;
       }
     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
-      MaybeHandle<Object> length_obj =
-          Object::GetProperty(object, isolate->factory()->length_string());
-      double length_num = length_obj.ToHandleChecked()->Number();
+      Handle<Object> length_obj;
+      // See ES6 22.1.3.1 step 7-a-ii
+      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+          isolate, length_obj,
+          Object::GetProperty(object, isolate->factory()->length_string()),
+          false);
+      ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, length_obj, Execution::ToLength(isolate, length_obj), false);
+      double length_num = length_obj->Number();
       uint32_t length = static_cast<uint32_t>(DoubleToInt32(length_num));
       ElementsAccessor* accessor = object->GetElementsAccessor();
       for (uint32_t i = 0; i < length; i++) {
@@ -455,10 +462,11 @@ static void CollectElementIndices(Handle<JSObject> object, uint32_t range,
   if (!iter.IsAtEnd()) {
     // The prototype will usually have no inherited element indices,
     // but we have to check.
-    CollectElementIndices(
+    return CollectElementIndices(
         Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter)), range,
         indices);
   }
+  return true;
 }


@@ -589,7 +597,7 @@ static bool IterateElements(Isolate* isolate, Handle<JSObject> receiver,
       List<uint32_t> indices(dict->Capacity() / 2);
       // Collect all indices in the object and the prototypes less
       // than length. This might introduce duplicates in the indices list.
-      CollectElementIndices(receiver, length, &indices);
+      if (!CollectElementIndices(receiver, length, &indices)) return false;
       indices.Sort(&compareUInt32);
       int j = 0;
       int n = indices.length();
Index: test/mjsunit/regress/regress-crbug-516775.js
diff --git a/test/mjsunit/regress/regress-crbug-516775.js b/test/mjsunit/regress/regress-crbug-516775.js
new file mode 100644
index 0000000000000000000000000000000000000000..f956109a2f9529b3c140ec9d09f059f20bcb4ec0
--- /dev/null
+++ b/test/mjsunit/regress/regress-crbug-516775.js
@@ -0,0 +1,20 @@
+// Copyright 2015 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
+
+function argument_with_length_getter(f) {
+  arguments.__defineGetter__('length', f);
+  return arguments;
+}
+
+var a1 = [];
+%NormalizeElements(a1);
+a1.__proto__ = argument_with_length_getter(function() { return 'boom' });
+[].concat(a1);
+
+var a2 = [];
+%NormalizeElements(a2);
+a2.__proto__ = argument_with_length_getter(function() { throw 'boom' });
+assertThrows(function() { [].concat(a2); });


--
--
v8-dev mailing list
v8-dev@googlegroups.com
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to v8-dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to