Wed, 05 Jun 2013 12:44:24 +0200
8015350: Array.prototype.reduceRight issue with large length and index
Reviewed-by: attila, sundar, lagergren
1.1 --- a/src/jdk/nashorn/internal/objects/NativeArray.java Wed Jun 05 12:17:10 2013 +0200 1.2 +++ b/src/jdk/nashorn/internal/objects/NativeArray.java Wed Jun 05 12:44:24 2013 +0200 1.3 @@ -75,7 +75,7 @@ 1.4 private static final MethodHandle FILTER_CALLBACK_INVOKER = createIteratorCallbackInvoker(boolean.class); 1.5 1.6 private static final MethodHandle REDUCE_CALLBACK_INVOKER = Bootstrap.createDynamicInvoker("dyn:call", Object.class, 1.7 - Object.class, Undefined.class, Object.class, Object.class, int.class, Object.class); 1.8 + Object.class, Undefined.class, Object.class, Object.class, long.class, Object.class); 1.9 private static final MethodHandle CALL_CMP = Bootstrap.createDynamicInvoker("dyn:call", double.class, 1.10 ScriptFunction.class, Object.class, Object.class, Object.class); 1.11 1.12 @@ -1086,7 +1086,7 @@ 1.13 private static boolean applyEvery(final Object self, final Object callbackfn, final Object thisArg) { 1.14 return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, true) { 1.15 @Override 1.16 - protected boolean forEach(final Object val, final int i) throws Throwable { 1.17 + protected boolean forEach(final Object val, final long i) throws Throwable { 1.18 return (result = (boolean)EVERY_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)); 1.19 } 1.20 }.apply(); 1.21 @@ -1104,7 +1104,7 @@ 1.22 public static Object some(final Object self, final Object callbackfn, final Object thisArg) { 1.23 return new IteratorAction<Boolean>(Global.toObject(self), callbackfn, thisArg, false) { 1.24 @Override 1.25 - protected boolean forEach(final Object val, final int i) throws Throwable { 1.26 + protected boolean forEach(final Object val, final long i) throws Throwable { 1.27 return !(result = (boolean)SOME_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)); 1.28 } 1.29 }.apply(); 1.30 @@ -1122,7 +1122,7 @@ 1.31 public static Object forEach(final Object self, final Object callbackfn, final Object thisArg) { 1.32 return new IteratorAction<Object>(Global.toObject(self), callbackfn, thisArg, ScriptRuntime.UNDEFINED) { 1.33 @Override 1.34 - protected boolean forEach(final Object val, final int i) throws Throwable { 1.35 + protected boolean forEach(final Object val, final long i) throws Throwable { 1.36 FOREACH_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); 1.37 return true; 1.38 } 1.39 @@ -1141,9 +1141,9 @@ 1.40 public static Object map(final Object self, final Object callbackfn, final Object thisArg) { 1.41 return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, null) { 1.42 @Override 1.43 - protected boolean forEach(final Object val, final int i) throws Throwable { 1.44 + protected boolean forEach(final Object val, final long i) throws Throwable { 1.45 final Object r = MAP_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); 1.46 - result.defineOwnProperty(index, r); 1.47 + result.defineOwnProperty((int)index, r); 1.48 return true; 1.49 } 1.50 1.51 @@ -1167,12 +1167,12 @@ 1.52 @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) 1.53 public static Object filter(final Object self, final Object callbackfn, final Object thisArg) { 1.54 return new IteratorAction<NativeArray>(Global.toObject(self), callbackfn, thisArg, new NativeArray()) { 1.55 - private int to = 0; 1.56 + private long to = 0; 1.57 1.58 @Override 1.59 - protected boolean forEach(final Object val, final int i) throws Throwable { 1.60 + protected boolean forEach(final Object val, final long i) throws Throwable { 1.61 if ((boolean)FILTER_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)) { 1.62 - result.defineOwnProperty(to++, val); 1.63 + result.defineOwnProperty((int)(to++), val); 1.64 } 1.65 return true; 1.66 } 1.67 @@ -1200,7 +1200,7 @@ 1.68 //if initial value is ScriptRuntime.UNDEFINED - step forward once. 1.69 return new IteratorAction<Object>(Global.toObject(self), callbackfn, ScriptRuntime.UNDEFINED, initialValue, iter) { 1.70 @Override 1.71 - protected boolean forEach(final Object val, final int i) throws Throwable { 1.72 + protected boolean forEach(final Object val, final long i) throws Throwable { 1.73 // TODO: why can't I declare the second arg as Undefined.class? 1.74 result = REDUCE_CALLBACK_INVOKER.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self); 1.75 return true; 1.76 @@ -1258,7 +1258,7 @@ 1.77 1.78 private static MethodHandle createIteratorCallbackInvoker(final Class<?> rtype) { 1.79 return Bootstrap.createDynamicInvoker("dyn:call", rtype, Object.class, Object.class, Object.class, 1.80 - int.class, Object.class); 1.81 + long.class, Object.class); 1.82 1.83 } 1.84 }
2.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java Wed Jun 05 12:17:10 2013 +0200 2.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java Wed Jun 05 12:44:24 2013 +0200 2.3 @@ -36,7 +36,7 @@ 2.4 protected final ScriptObject array; 2.5 2.6 /** length of array */ 2.7 - protected final int length; 2.8 + protected final long length; 2.9 2.10 /** 2.11 * Constructor 2.12 @@ -46,7 +46,7 @@ 2.13 protected ArrayIterator(final ScriptObject array, final boolean includeUndefined) { 2.14 super(includeUndefined); 2.15 this.array = array; 2.16 - this.length = (int) array.getArray().length(); 2.17 + this.length = array.getArray().length(); 2.18 } 2.19 2.20 /** 2.21 @@ -63,7 +63,7 @@ 2.22 } 2.23 2.24 @Override 2.25 - public int getLength() { 2.26 + public long getLength() { 2.27 return length; 2.28 } 2.29
3.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java Wed Jun 05 12:17:10 2013 +0200 3.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java Wed Jun 05 12:44:24 2013 +0200 3.3 @@ -38,7 +38,7 @@ 3.4 abstract public class ArrayLikeIterator<T> implements Iterator<T> { 3.5 3.6 /** current element index in iteration */ 3.7 - protected int index; 3.8 + protected long index; 3.9 3.10 /** should undefined elements be included in the iteration? */ 3.11 protected final boolean includeUndefined; 3.12 @@ -65,7 +65,7 @@ 3.13 * Go the the next valid element index of the iterator 3.14 * @return next index 3.15 */ 3.16 - protected int bumpIndex() { 3.17 + protected long bumpIndex() { 3.18 return index++; 3.19 } 3.20 3.21 @@ -73,7 +73,7 @@ 3.22 * Return the next valid element index of the iterator 3.23 * @return next index 3.24 */ 3.25 - public int nextIndex() { 3.26 + public long nextIndex() { 3.27 return index; 3.28 } 3.29 3.30 @@ -86,7 +86,7 @@ 3.31 * Get the length of the iteration 3.32 * @return length 3.33 */ 3.34 - public abstract int getLength(); 3.35 + public abstract long getLength(); 3.36 3.37 /** 3.38 * ArrayLikeIterator factory
4.1 --- a/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java Wed Jun 05 12:17:10 2013 +0200 4.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java Wed Jun 05 12:44:24 2013 +0200 4.3 @@ -47,7 +47,7 @@ 4.4 } 4.5 4.6 @Override 4.7 - public int getLength() { 4.8 + public long getLength() { 4.9 return 0; 4.10 } 4.11 }
5.1 --- a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Wed Jun 05 12:17:10 2013 +0200 5.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java Wed Jun 05 12:44:24 2013 +0200 5.3 @@ -49,7 +49,7 @@ 5.4 protected T result; 5.5 5.6 /** Current array index of iterator */ 5.7 - protected int index; 5.8 + protected long index; 5.9 5.10 /** Iterator object */ 5.11 private final ArrayLikeIterator<Object> iter; 5.12 @@ -134,6 +134,6 @@ 5.13 * 5.14 * @throws Throwable if invocation throws an exception/error 5.15 */ 5.16 - protected abstract boolean forEach(final Object val, final int i) throws Throwable; 5.17 + protected abstract boolean forEach(final Object val, final long i) throws Throwable; 5.18 5.19 }
6.1 --- a/src/jdk/nashorn/internal/runtime/arrays/MapIterator.java Wed Jun 05 12:17:10 2013 +0200 6.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/MapIterator.java Wed Jun 05 12:44:24 2013 +0200 6.3 @@ -49,8 +49,8 @@ 6.4 } 6.5 6.6 @Override 6.7 - public int getLength() { 6.8 - return (int) length; 6.9 + public long getLength() { 6.10 + return length; 6.11 } 6.12 6.13 @Override
7.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ReverseArrayIterator.java Wed Jun 05 12:17:10 2013 +0200 7.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseArrayIterator.java Wed Jun 05 12:44:24 2013 +0200 7.3 @@ -39,7 +39,7 @@ 7.4 */ 7.5 public ReverseArrayIterator(final ScriptObject array, final boolean includeUndefined) { 7.6 super(array, includeUndefined); 7.7 - this.index = (int) (array.getArray().length() - 1); 7.8 + this.index = array.getArray().length() - 1; 7.9 } 7.10 7.11 @Override 7.12 @@ -53,7 +53,7 @@ 7.13 } 7.14 7.15 @Override 7.16 - protected int bumpIndex() { 7.17 + protected long bumpIndex() { 7.18 return index--; 7.19 } 7.20 }
8.1 --- a/src/jdk/nashorn/internal/runtime/arrays/ReverseMapIterator.java Wed Jun 05 12:17:10 2013 +0200 8.2 +++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseMapIterator.java Wed Jun 05 12:44:24 2013 +0200 8.3 @@ -35,7 +35,7 @@ 8.4 8.5 ReverseMapIterator(final ScriptObject obj, final boolean includeUndefined) { 8.6 super(obj, includeUndefined); 8.7 - this.index = JSType.toInt32(obj.getLength()) - 1; 8.8 + this.index = JSType.toUint32(obj.getLength()) - 1; 8.9 } 8.10 8.11 @Override 8.12 @@ -49,7 +49,7 @@ 8.13 } 8.14 8.15 @Override 8.16 - protected int bumpIndex() { 8.17 + protected long bumpIndex() { 8.18 return index--; 8.19 } 8.20 }
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 9.2 +++ b/test/script/basic/JDK-8015350.js Wed Jun 05 12:44:24 2013 +0200 9.3 @@ -0,0 +1,51 @@ 9.4 +/* 9.5 + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 9.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 9.7 + * 9.8 + * This code is free software; you can redistribute it and/or modify it 9.9 + * under the terms of the GNU General Public License version 2 only, as 9.10 + * published by the Free Software Foundation. 9.11 + * 9.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 9.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 9.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 9.15 + * version 2 for more details (a copy is included in the LICENSE file that 9.16 + * accompanied this code). 9.17 + * 9.18 + * You should have received a copy of the GNU General Public License version 9.19 + * 2 along with this work; if not, write to the Free Software Foundation, 9.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 9.21 + * 9.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 9.23 + * or visit www.oracle.com if you need additional information or have any 9.24 + * questions. 9.25 + */ 9.26 + 9.27 +/** 9.28 + * JDK-8015350: Array.prototype.reduceRight issue with large length and index 9.29 + * 9.30 + * @test 9.31 + * @run 9.32 + */ 9.33 + 9.34 +function reduce(obj) { 9.35 + try { 9.36 + Array.prototype.reduceRight.call(obj, function(acc, v, i, o){ 9.37 + print(v + i); 9.38 + throw "stop"; 9.39 + }, 0); 9.40 + } catch (error) { 9.41 + print(error); 9.42 + } 9.43 +} 9.44 + 9.45 +// array-like object 9.46 +reduce({ 9.47 + length:0xffffffff, 9.48 + 0xfffffffe: "index: " 9.49 +}); 9.50 + 9.51 +// actual sparse array 9.52 +var array = []; 9.53 +array[0xfffffffe] = "index: "; 9.54 +reduce(array);
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 10.2 +++ b/test/script/basic/JDK-8015350.js.EXPECTED Wed Jun 05 12:44:24 2013 +0200 10.3 @@ -0,0 +1,4 @@ 10.4 +index: 4294967294 10.5 +stop 10.6 +index: 4294967294 10.7 +stop