diff --git a/changelog.md b/changelog.md index bdd22d6ed..87d5a2a65 100644 --- a/changelog.md +++ b/changelog.md @@ -1,13 +1,9 @@ ## Fixes/improvements -* Reverted Internet Card code to OC 1.7.7, fixing the many related regressions. -* Fixed "number expected, got number" being displayed instead of "number has no integer representation" on Lua 5.3+. -* Fixed math.randomseed() not working with non-integer values. +* [#3620] Fixed OC 1.8.0+ regression involving API arguments and numbers. ## OpenOS fixes/improvements -* Fixed OpenOS version number. - ## List of contributors asie diff --git a/src/main/scala/li/cil/oc/server/machine/ArgumentsImpl.scala b/src/main/scala/li/cil/oc/server/machine/ArgumentsImpl.scala index 27e5e30d2..c2edc71c9 100644 --- a/src/main/scala/li/cil/oc/server/machine/ArgumentsImpl.scala +++ b/src/main/scala/li/cil/oc/server/machine/ArgumentsImpl.scala @@ -58,10 +58,28 @@ class ArgumentsImpl(val args: Seq[AnyRef]) extends Arguments { } def checkInteger(index: Int) = { - checkIndex(index, "number") + checkIndex(index, "integer") args(index) match { + case value: java.lang.Double => + if (!java.lang.Double.isFinite(value) || value < java.lang.Integer.MIN_VALUE || value > java.lang.Integer.MAX_VALUE) { + throw intError(index, value) + } else { + value.intValue + } + case value: java.lang.Float => + if (!java.lang.Float.isFinite(value) || value < java.lang.Integer.MIN_VALUE || value > java.lang.Integer.MAX_VALUE) { + throw intError(index, value) + } else { + value.intValue + } + case value: java.lang.Long => + if (value < java.lang.Integer.MIN_VALUE || value > java.lang.Integer.MAX_VALUE) { + throw intError(index, value) + } else { + value.intValue + } case value: java.lang.Number => value.intValue - case value => throw typeError(index, value, "number") + case value => throw typeError(index, value, "integer") } } @@ -71,10 +89,22 @@ class ArgumentsImpl(val args: Seq[AnyRef]) extends Arguments { } def checkLong(index: Int) = { - checkIndex(index, "number") + checkIndex(index, "integer") args(index) match { + case value: java.lang.Double => + if (!java.lang.Double.isFinite(value) || value < java.lang.Long.MIN_VALUE || value > java.lang.Long.MAX_VALUE) { + throw intError(index, value) + } else { + value.longValue + } + case value: java.lang.Float => + if (!java.lang.Float.isFinite(value) || value < java.lang.Long.MIN_VALUE || value > java.lang.Long.MAX_VALUE) { + throw intError(index, value) + } else { + value.longValue + } case value: java.lang.Number => value.longValue - case value => throw typeError(index, value, "number") + case value => throw typeError(index, value, "integer") } } @@ -157,22 +187,31 @@ class ArgumentsImpl(val args: Seq[AnyRef]) extends Arguments { def isDouble(index: Int) = index >= 0 && index < count && (args(index) match { - case value: java.lang.Float => true - case value: java.lang.Double => true + case value: java.lang.Number => true case _ => false }) def isInteger(index: Int) = index >= 0 && index < count && (args(index) match { - case value: java.lang.Byte => true - case value: java.lang.Short => true - case value: java.lang.Integer => true - case value: java.lang.Long => true - case value: java.lang.Double => true + case value: java.lang.Double => + java.lang.Double.isFinite(value) && value >= java.lang.Integer.MIN_VALUE && value <= java.lang.Integer.MAX_VALUE + case value: java.lang.Float => + java.lang.Float.isFinite(value) && value >= java.lang.Integer.MIN_VALUE && value <= java.lang.Integer.MAX_VALUE + case value: java.lang.Long => + value >= java.lang.Integer.MIN_VALUE && value <= java.lang.Integer.MAX_VALUE + case value: java.lang.Number => true case _ => false }) - def isLong(index: Int) = isInteger(index) + def isLong(index: Int) = + index >= 0 && index < count && (args(index) match { + case value: java.lang.Double => + java.lang.Double.isFinite(value) && value >= java.lang.Long.MIN_VALUE && value <= java.lang.Long.MAX_VALUE + case value: java.lang.Float => + java.lang.Float.isFinite(value) && value >= java.lang.Long.MIN_VALUE && value <= java.lang.Long.MAX_VALUE + case value: java.lang.Number => true + case _ => false + }) def isString(index: Int) = index >= 0 && index < count && (args(index) match { @@ -222,6 +261,10 @@ class ArgumentsImpl(val args: Seq[AnyRef]) extends Arguments { new IllegalArgumentException( s"bad argument #${index + 1} ($want expected, got ${typeName(have)})") + private def intError(index: Int, have: AnyRef) = + new IllegalArgumentException( + s"bad argument #${index + 1} (${typeName(have)} has no integer representation)") + private def typeName(value: AnyRef): String = value match { case null | Unit | None => "nil" case _: java.lang.Boolean => "boolean" @@ -229,7 +272,7 @@ class ArgumentsImpl(val args: Seq[AnyRef]) extends Arguments { case _: java.lang.Short => "integer" case _: java.lang.Integer => "integer" case _: java.lang.Long => "integer" - case _: java.lang.Number => "double" + case _: java.lang.Number => "number" case _: java.lang.String => "string" case _: Array[Byte] => "string" case value: java.util.Map[_, _] => "table"