From 1cd602783cf8f65202e83957c7a907b2166c73b5 Mon Sep 17 00:00:00 2001 From: hannesw Date: Wed, 5 Jun 2013 12:44:24 +0200 Subject: [PATCH] 8015350: Array.prototype.reduceRight issue with large length and index Reviewed-by: attila, sundar, lagergren --- .../nashorn/internal/objects/NativeArray.java | 22 ++++---- .../runtime/arrays/ArrayIterator.java | 6 +-- .../runtime/arrays/ArrayLikeIterator.java | 8 +-- .../arrays/EmptyArrayLikeIterator.java | 2 +- .../runtime/arrays/IteratorAction.java | 4 +- .../internal/runtime/arrays/MapIterator.java | 4 +- .../runtime/arrays/ReverseArrayIterator.java | 4 +- .../runtime/arrays/ReverseMapIterator.java | 4 +- test/script/basic/JDK-8015350.js | 51 +++++++++++++++++++ test/script/basic/JDK-8015350.js.EXPECTED | 4 ++ 10 files changed, 82 insertions(+), 27 deletions(-) create mode 100644 test/script/basic/JDK-8015350.js create mode 100644 test/script/basic/JDK-8015350.js.EXPECTED diff --git a/src/jdk/nashorn/internal/objects/NativeArray.java b/src/jdk/nashorn/internal/objects/NativeArray.java index 6f9fbcec..9736376b 100644 --- a/src/jdk/nashorn/internal/objects/NativeArray.java +++ b/src/jdk/nashorn/internal/objects/NativeArray.java @@ -75,7 +75,7 @@ public final class NativeArray extends ScriptObject { private static final MethodHandle FILTER_CALLBACK_INVOKER = createIteratorCallbackInvoker(boolean.class); private static final MethodHandle REDUCE_CALLBACK_INVOKER = Bootstrap.createDynamicInvoker("dyn:call", Object.class, - Object.class, Undefined.class, Object.class, Object.class, int.class, Object.class); + Object.class, Undefined.class, Object.class, Object.class, long.class, Object.class); private static final MethodHandle CALL_CMP = Bootstrap.createDynamicInvoker("dyn:call", double.class, ScriptFunction.class, Object.class, Object.class, Object.class); @@ -1086,7 +1086,7 @@ public final class NativeArray extends ScriptObject { private static boolean applyEvery(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction(Global.toObject(self), callbackfn, thisArg, true) { @Override - protected boolean forEach(final Object val, final int i) throws Throwable { + protected boolean forEach(final Object val, final long i) throws Throwable { return (result = (boolean)EVERY_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)); } }.apply(); @@ -1104,7 +1104,7 @@ public final class NativeArray extends ScriptObject { public static Object some(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction(Global.toObject(self), callbackfn, thisArg, false) { @Override - protected boolean forEach(final Object val, final int i) throws Throwable { + protected boolean forEach(final Object val, final long i) throws Throwable { return !(result = (boolean)SOME_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)); } }.apply(); @@ -1122,7 +1122,7 @@ public final class NativeArray extends ScriptObject { public static Object forEach(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction(Global.toObject(self), callbackfn, thisArg, ScriptRuntime.UNDEFINED) { @Override - protected boolean forEach(final Object val, final int i) throws Throwable { + protected boolean forEach(final Object val, final long i) throws Throwable { FOREACH_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); return true; } @@ -1141,9 +1141,9 @@ public final class NativeArray extends ScriptObject { public static Object map(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction(Global.toObject(self), callbackfn, thisArg, null) { @Override - protected boolean forEach(final Object val, final int i) throws Throwable { + protected boolean forEach(final Object val, final long i) throws Throwable { final Object r = MAP_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self); - result.defineOwnProperty(index, r); + result.defineOwnProperty((int)index, r); return true; } @@ -1167,12 +1167,12 @@ public final class NativeArray extends ScriptObject { @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) public static Object filter(final Object self, final Object callbackfn, final Object thisArg) { return new IteratorAction(Global.toObject(self), callbackfn, thisArg, new NativeArray()) { - private int to = 0; + private long to = 0; @Override - protected boolean forEach(final Object val, final int i) throws Throwable { + protected boolean forEach(final Object val, final long i) throws Throwable { if ((boolean)FILTER_CALLBACK_INVOKER.invokeExact(callbackfn, thisArg, val, i, self)) { - result.defineOwnProperty(to++, val); + result.defineOwnProperty((int)(to++), val); } return true; } @@ -1200,7 +1200,7 @@ public final class NativeArray extends ScriptObject { //if initial value is ScriptRuntime.UNDEFINED - step forward once. return new IteratorAction(Global.toObject(self), callbackfn, ScriptRuntime.UNDEFINED, initialValue, iter) { @Override - protected boolean forEach(final Object val, final int i) throws Throwable { + protected boolean forEach(final Object val, final long i) throws Throwable { // TODO: why can't I declare the second arg as Undefined.class? result = REDUCE_CALLBACK_INVOKER.invokeExact(callbackfn, ScriptRuntime.UNDEFINED, result, val, i, self); return true; @@ -1258,7 +1258,7 @@ public final class NativeArray extends ScriptObject { private static MethodHandle createIteratorCallbackInvoker(final Class rtype) { return Bootstrap.createDynamicInvoker("dyn:call", rtype, Object.class, Object.class, Object.class, - int.class, Object.class); + long.class, Object.class); } } diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java index 3b9905a2..e250c748 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayIterator.java @@ -36,7 +36,7 @@ public class ArrayIterator extends ArrayLikeIterator { protected final ScriptObject array; /** length of array */ - protected final int length; + protected final long length; /** * Constructor @@ -46,7 +46,7 @@ public class ArrayIterator extends ArrayLikeIterator { protected ArrayIterator(final ScriptObject array, final boolean includeUndefined) { super(includeUndefined); this.array = array; - this.length = (int) array.getArray().length(); + this.length = array.getArray().length(); } /** @@ -63,7 +63,7 @@ public class ArrayIterator extends ArrayLikeIterator { } @Override - public int getLength() { + public long getLength() { return length; } diff --git a/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java index 5061683a..48505f44 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java +++ b/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java @@ -38,7 +38,7 @@ import jdk.nashorn.internal.runtime.ScriptObject; abstract public class ArrayLikeIterator implements Iterator { /** current element index in iteration */ - protected int index; + protected long index; /** should undefined elements be included in the iteration? */ protected final boolean includeUndefined; @@ -65,7 +65,7 @@ abstract public class ArrayLikeIterator implements Iterator { * Go the the next valid element index of the iterator * @return next index */ - protected int bumpIndex() { + protected long bumpIndex() { return index++; } @@ -73,7 +73,7 @@ abstract public class ArrayLikeIterator implements Iterator { * Return the next valid element index of the iterator * @return next index */ - public int nextIndex() { + public long nextIndex() { return index; } @@ -86,7 +86,7 @@ abstract public class ArrayLikeIterator implements Iterator { * Get the length of the iteration * @return length */ - public abstract int getLength(); + public abstract long getLength(); /** * ArrayLikeIterator factory diff --git a/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java b/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java index 5264283a..e94f8cf3 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java +++ b/src/jdk/nashorn/internal/runtime/arrays/EmptyArrayLikeIterator.java @@ -47,7 +47,7 @@ final class EmptyArrayLikeIterator extends ArrayLikeIterator { } @Override - public int getLength() { + public long getLength() { return 0; } } diff --git a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java index 9fb4eed8..7568f41b 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java +++ b/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java @@ -49,7 +49,7 @@ public abstract class IteratorAction { protected T result; /** Current array index of iterator */ - protected int index; + protected long index; /** Iterator object */ private final ArrayLikeIterator iter; @@ -134,6 +134,6 @@ public abstract class IteratorAction { * * @throws Throwable if invocation throws an exception/error */ - protected abstract boolean forEach(final Object val, final int i) throws Throwable; + protected abstract boolean forEach(final Object val, final long i) throws Throwable; } diff --git a/src/jdk/nashorn/internal/runtime/arrays/MapIterator.java b/src/jdk/nashorn/internal/runtime/arrays/MapIterator.java index fdf9d3a4..f8b40cfe 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/MapIterator.java +++ b/src/jdk/nashorn/internal/runtime/arrays/MapIterator.java @@ -49,8 +49,8 @@ class MapIterator extends ArrayLikeIterator { } @Override - public int getLength() { - return (int) length; + public long getLength() { + return length; } @Override diff --git a/src/jdk/nashorn/internal/runtime/arrays/ReverseArrayIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ReverseArrayIterator.java index 72a47a93..f9ba0ff0 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/ReverseArrayIterator.java +++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseArrayIterator.java @@ -39,7 +39,7 @@ public final class ReverseArrayIterator extends ArrayIterator { */ public ReverseArrayIterator(final ScriptObject array, final boolean includeUndefined) { super(array, includeUndefined); - this.index = (int) (array.getArray().length() - 1); + this.index = array.getArray().length() - 1; } @Override @@ -53,7 +53,7 @@ public final class ReverseArrayIterator extends ArrayIterator { } @Override - protected int bumpIndex() { + protected long bumpIndex() { return index--; } } diff --git a/src/jdk/nashorn/internal/runtime/arrays/ReverseMapIterator.java b/src/jdk/nashorn/internal/runtime/arrays/ReverseMapIterator.java index 760ac720..0822b5a4 100644 --- a/src/jdk/nashorn/internal/runtime/arrays/ReverseMapIterator.java +++ b/src/jdk/nashorn/internal/runtime/arrays/ReverseMapIterator.java @@ -35,7 +35,7 @@ final class ReverseMapIterator extends MapIterator { ReverseMapIterator(final ScriptObject obj, final boolean includeUndefined) { super(obj, includeUndefined); - this.index = JSType.toInt32(obj.getLength()) - 1; + this.index = JSType.toUint32(obj.getLength()) - 1; } @Override @@ -49,7 +49,7 @@ final class ReverseMapIterator extends MapIterator { } @Override - protected int bumpIndex() { + protected long bumpIndex() { return index--; } } diff --git a/test/script/basic/JDK-8015350.js b/test/script/basic/JDK-8015350.js new file mode 100644 index 00000000..c8202969 --- /dev/null +++ b/test/script/basic/JDK-8015350.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * JDK-8015350: Array.prototype.reduceRight issue with large length and index + * + * @test + * @run + */ + +function reduce(obj) { + try { + Array.prototype.reduceRight.call(obj, function(acc, v, i, o){ + print(v + i); + throw "stop"; + }, 0); + } catch (error) { + print(error); + } +} + +// array-like object +reduce({ + length:0xffffffff, + 0xfffffffe: "index: " +}); + +// actual sparse array +var array = []; +array[0xfffffffe] = "index: "; +reduce(array); diff --git a/test/script/basic/JDK-8015350.js.EXPECTED b/test/script/basic/JDK-8015350.js.EXPECTED new file mode 100644 index 00000000..e8bda2c4 --- /dev/null +++ b/test/script/basic/JDK-8015350.js.EXPECTED @@ -0,0 +1,4 @@ +index: 4294967294 +stop +index: 4294967294 +stop -- GitLab