diff --git a/src/main/java/cc/tweaked/cobalt/internal/string/NumberParser.java b/src/main/java/cc/tweaked/cobalt/internal/string/NumberParser.java index 4f7e5719..6c90690f 100644 --- a/src/main/java/cc/tweaked/cobalt/internal/string/NumberParser.java +++ b/src/main/java/cc/tweaked/cobalt/internal/string/NumberParser.java @@ -71,7 +71,16 @@ private static double scanLong(int base, byte[] bytes, int start, int end) { } if (digit >= base) return Double.NaN; - x = x * base + digit; + + if (base == 10) { + try { + x = Math.addExact(Math.multiplyExact(x, base), digit); + } catch (ArithmeticException e) { + return Double.NaN; + } + } else { + x = x * base + digit; + } } return x; } @@ -119,7 +128,7 @@ private static double scanDouble(byte[] bytes, int start, int end) { } private static double scanHexDouble(byte[] bytes, int index, int end) { - long result = 0; // The mantissa + double result = 0; // The mantissa int exponent = 0; int sigDigits = 0, nonSigDigits = 0; // Number of significant digits and non-significant digits (leading 0s). @@ -187,6 +196,6 @@ private static double scanHexDouble(byte[] bytes, int index, int end) { exponent += givenExponent; } - return Math.scalb((double) result, exponent); + return Math.scalb(result, exponent); } } diff --git a/src/main/java/org/squiddev/cobalt/LuaDouble.java b/src/main/java/org/squiddev/cobalt/LuaDouble.java index b405104e..dc596c7c 100644 --- a/src/main/java/org/squiddev/cobalt/LuaDouble.java +++ b/src/main/java/org/squiddev/cobalt/LuaDouble.java @@ -139,7 +139,7 @@ public String toString() { @Override public LuaString checkLuaString() { long l = (long) v; - if (l == v) return ValueFactory.valueOf(Long.toString(l)); + if (l == v && l != Long.MAX_VALUE) return ValueFactory.valueOf(Long.toString(l)); if (Double.isNaN(v)) return STR_NAN; if (Double.isInfinite(v)) return v < 0 ? STR_NEGINF : STR_POSINF; diff --git a/src/test/resources/spec/base_spec.lua b/src/test/resources/spec/base_spec.lua index c302d39b..1ba38738 100644 --- a/src/test/resources/spec/base_spec.lua +++ b/src/test/resources/spec/base_spec.lua @@ -65,6 +65,10 @@ describe("The base library", function() expect('' .. 12):eq('12') expect(12.0 .. ''):eq('12') expect(tostring(-1203 + 0.0)):eq("-1203") end) + + it("correctly handles 2^63", function() + expect(tostring(math.floor(2^63))):not_equals("9223372036854775807") + end) end) it("tables", function() expect(tostring {}):str_match('^table:') end) diff --git a/src/test/resources/spec/parser_spec.lua b/src/test/resources/spec/parser_spec.lua index 99243dd0..8faa22b4 100644 --- a/src/test/resources/spec/parser_spec.lua +++ b/src/test/resources/spec/parser_spec.lua @@ -1,6 +1,14 @@ describe("The Lua lexer/parser", function() describe("numbers", function() local load = loadstring or load + it("only wraps around hexadecimal numerals with neither an exponent nor radix point", function() + -- See https://github.com/cc-tweaked/Cobalt/issues/88 + expect(tonumber(("9"):rep(19))):eq(1e19) + expect(tonumber("0xffffffffffffffff")):eq(-1) + expect(tonumber("0xffffffffffffffff.0")):eq(2^64) + expect(tonumber("0xffffffffffffffffp0")):eq(2^64) + end) + it("rejects numbers ending in 'f' or 'd'", function() -- Java's Double.parseDouble accepts "2f" and "2d" as a valid number. Make sure we don't. -- See https://github.com/SquidDev/Cobalt/issues/71