Skip to content

Commit

Permalink
Array.prototype.{pop|push|reverse} didn't properly call ToObject on t…
Browse files Browse the repository at this point in the history
…heir argument. (#12)
  • Loading branch information
szegedi authored Dec 30, 2020
1 parent 934de5c commit 88396b5
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -896,30 +896,30 @@ public static Object popObject(final Object self) {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object pop(final Object self) {
try {
final ScriptObject sobj = (ScriptObject)self;
final Object obj = Global.toObject(self);
if (!(obj instanceof ScriptObject)) {
return ScriptRuntime.UNDEFINED;
}
final ScriptObject sobj = (ScriptObject)obj;

if (bulkable(sobj)) {
return sobj.getArray().pop();
}
if (bulkable(sobj)) {
return sobj.getArray().pop();
}

final long len = JSType.toUint32(sobj.getLength());
final long len = JSType.toUint32(sobj.getLength());

if (len == 0) {
sobj.set("length", 0, CALLSITE_STRICT);
return ScriptRuntime.UNDEFINED;
}
if (len == 0) {
sobj.set("length", 0, CALLSITE_STRICT);
return ScriptRuntime.UNDEFINED;
}

final long index = len - 1;
final Object element = sobj.get(index);
final long index = len - 1;
final Object element = sobj.get(index);

sobj.delete(index, true);
sobj.set("length", index, CALLSITE_STRICT);
sobj.delete(index, true);
sobj.set("length", index, CALLSITE_STRICT);

return element;
} catch (final ClassCastException | NullPointerException e) {
throw typeError("not.an.object", ScriptRuntime.safeToString(self));
}
return element;
}

/**
Expand Down Expand Up @@ -974,7 +974,11 @@ public static double pushObject(final Object self, final Object arg) {
@Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
public static Object push(final Object self, final Object... args) {
try {
final ScriptObject sobj = (ScriptObject)self;
final Object obj = Global.toObject(self);
if (!(obj instanceof ScriptObject)) {
return args.length;
}
final ScriptObject sobj = (ScriptObject)obj;

if (bulkable(sobj) && sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
final ArrayData newData = sobj.getArray().push(true, args);
Expand All @@ -999,26 +1003,26 @@ public static Object push(final Object self, final Object... args) {
*
* @param self self reference
* @param arg argument to push
* @return array after pushes
* @return array length after pushes
*/
@SpecializedFunction
public static double push(final Object self, final Object arg) {
try {
final ScriptObject sobj = (ScriptObject)self;
final ArrayData arrayData = sobj.getArray();
final long length = arrayData.length();
if (bulkable(sobj) && length < JSType.MAX_UINT) {
sobj.setArray(arrayData.push(true, arg));
return length + 1;
}

long len = JSType.toUint32(sobj.getLength());
sobj.set(len++, arg, CALLSITE_STRICT);
sobj.set("length", len, CALLSITE_STRICT);
return len;
} catch (final ClassCastException | NullPointerException e) {
throw typeError("not.an.object", ScriptRuntime.safeToString(self));
final Object obj = Global.toObject(self);
if (!(obj instanceof ScriptObject)) {
return 1d;
}
final ScriptObject sobj = (ScriptObject)obj;
final ArrayData arrayData = sobj.getArray();
final long length = arrayData.length();
if (bulkable(sobj) && length < JSType.MAX_UINT) {
sobj.setArray(arrayData.push(true, arg));
return length + 1;
}

long len = JSType.toUint32(sobj.getLength());
sobj.set(len++, arg, CALLSITE_STRICT);
sobj.set("length", len, CALLSITE_STRICT);
return len;
}

/**
Expand All @@ -1029,33 +1033,34 @@ public static double push(final Object self, final Object arg) {
*/
@Function(attributes = Attribute.NOT_ENUMERABLE)
public static Object reverse(final Object self) {
try {
final ScriptObject sobj = (ScriptObject)self;
final long len = JSType.toUint32(sobj.getLength());
final long middle = len / 2;

for (long lower = 0; lower != middle; lower++) {
final long upper = len - lower - 1;
final Object lowerValue = sobj.get(lower);
final Object upperValue = sobj.get(upper);
final boolean lowerExists = sobj.has(lower);
final boolean upperExists = sobj.has(upper);

if (lowerExists && upperExists) {
sobj.set(lower, upperValue, CALLSITE_STRICT);
sobj.set(upper, lowerValue, CALLSITE_STRICT);
} else if (!lowerExists && upperExists) {
sobj.set(lower, upperValue, CALLSITE_STRICT);
sobj.delete(upper, true);
} else if (lowerExists) {
sobj.delete(lower, true);
sobj.set(upper, lowerValue, CALLSITE_STRICT);
}
final Object obj = Global.toObject(self);
if (!(obj instanceof ScriptObject)) {
return obj;
}

final ScriptObject sobj = (ScriptObject)obj;
final long len = JSType.toUint32(sobj.getLength());
final long middle = len / 2;

for (long lower = 0; lower != middle; lower++) {
final long upper = len - lower - 1;
final Object lowerValue = sobj.get(lower);
final Object upperValue = sobj.get(upper);
final boolean lowerExists = sobj.has(lower);
final boolean upperExists = sobj.has(upper);

if (lowerExists && upperExists) {
sobj.set(lower, upperValue, CALLSITE_STRICT);
sobj.set(upper, lowerValue, CALLSITE_STRICT);
} else if (!lowerExists && upperExists) {
sobj.set(lower, upperValue, CALLSITE_STRICT);
sobj.delete(upper, true);
} else if (lowerExists) {
sobj.delete(lower, true);
sobj.set(upper, lowerValue, CALLSITE_STRICT);
}
return sobj;
} catch (final ClassCastException | NullPointerException e) {
throw typeError("not.an.object", ScriptRuntime.safeToString(self));
}
return sobj;
}

/**
Expand Down
37 changes: 37 additions & 0 deletions test/nashorn/script/basic/JDK-8240298.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* Copyright (c) 2020, 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-8240298: Array.prototype.{push|pop|reverse} must call ToObject on their argument
*
* @test
* @run
*/

print(typeof Array.prototype.pop.call(false) == "undefined")
print(Array.prototype.push.call(false) == 0)
print(Array.prototype.push.call(false, 2) == 1)
print(Array.prototype.push.call(false, 2, 4, 6) == 3)
var x = Array.prototype.reverse.call(false)
print(typeof x == "object")
print(x.toString() == "false")
6 changes: 6 additions & 0 deletions test/nashorn/script/basic/JDK-8240298.js.EXPECTED
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
true
true
true
true
true
true

0 comments on commit 88396b5

Please sign in to comment.