From daf80a289404d3c34ef1ba9bd5dc6e6894b31cbd Mon Sep 17 00:00:00 2001 From: Ronald Brill Date: Wed, 16 Oct 2024 17:52:59 +0200 Subject: [PATCH] fix endless loop in ScriptRuntimem toString() and toNumber() and add tests to ensure backward comatibility --- .../org/mozilla/javascript/ScriptRuntime.java | 23 +++++++--- .../javascript/tests/ScriptRuntimeTest.java | 45 +++++++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 rhino/src/test/java/org/mozilla/javascript/tests/ScriptRuntimeTest.java diff --git a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java index 9dd071c368..b78682d8f4 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java +++ b/rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java @@ -437,9 +437,15 @@ public static double toNumber(Object val) { if (val instanceof CharSequence) return toNumber(val.toString()); if (val instanceof Boolean) return ((Boolean) val).booleanValue() ? 1 : +0.0; if (isSymbol(val)) throw typeErrorById("msg.not.a.number"); - // Assert: val is an Object - val = toPrimitive(val, NumberClass); - // Assert: val is a primitive + + if (val instanceof Scriptable) { + // Assert: val is an Object + val = toPrimitive(val, NumberClass); + // Assert: val is a primitive + } else { + warnAboutNonJSObject(val); + return Double.NaN; + } } } @@ -1025,9 +1031,14 @@ public static String toString(Object val) { if (isSymbol(val)) { throw typeErrorById("msg.not.a.string"); } - // Assert: val is an Object - val = toPrimitive(val, StringClass); - // Assert: val is a primitive + if (val instanceof Scriptable) { + // Assert: val is an Object + val = toPrimitive(val, StringClass); + // Assert: val is a primitive + } else { + warnAboutNonJSObject(val); + return val.toString(); + } } } diff --git a/rhino/src/test/java/org/mozilla/javascript/tests/ScriptRuntimeTest.java b/rhino/src/test/java/org/mozilla/javascript/tests/ScriptRuntimeTest.java new file mode 100644 index 0000000000..af0253389e --- /dev/null +++ b/rhino/src/test/java/org/mozilla/javascript/tests/ScriptRuntimeTest.java @@ -0,0 +1,45 @@ +package org.mozilla.javascript.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.mozilla.javascript.ScriptRuntime; +import org.mozilla.javascript.Scriptable; + +/** + * Test cases for the {@link org.mozilla.javascript.ScriptRuntime}. + * + * @author Ronald Brill + */ +public class ScriptRuntimeTest { + + /** + * Test toNumber(Object) to work with non Scriptable objects that are not supported by the + * Rhino. There was a bug that in this case the impl stucks in an endless loop. + */ + @Test + public void toNumberNotScriptable() { + assertEquals(Double.NaN, ScriptRuntime.toNumber(Scriptable.NOT_FOUND), 0.00001); + assertEquals(Double.NaN, ScriptRuntime.toNumber(new Object()), 0.00001); + assertEquals(Double.NaN, ScriptRuntime.toNumber(new NullPointerException("NPE")), 0.00001); + } + + /** + * Test toString(Object) to work with non Scriptable objects that are not supported by the + * Rhino. There was a bug that in this case the impl stucks in an endless loop. + */ + @Test + public void toStringNotScriptable() { + assertTrue( + ScriptRuntime.toString(Scriptable.NOT_FOUND) + .startsWith("org.mozilla.javascript.UniqueTag@")); + assertTrue(ScriptRuntime.toString(Scriptable.NOT_FOUND).endsWith("NOT_FOUND")); + + assertTrue(ScriptRuntime.toString(new Object()).startsWith("java.lang.Object@")); + + assertEquals( + "java.lang.NullPointerException: NPE", + ScriptRuntime.toString(new NullPointerException("NPE"))); + } +}