diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index 288521e1c..d86c347ad 100644 --- a/ext/json/ext/parser/parser.c +++ b/ext/json/ext/parser/parser.c @@ -1169,11 +1169,11 @@ static inline VALUE json_decode_float(JSON_ParserConfig *config, uint64_t mantis return rb_funcallv(config->decimal_class, config->decimal_method_id, 1, &text); } - if (RB_UNLIKELY(exponent > INT32_MAX)) { + if (RB_UNLIKELY(exponent >= (int64_t)INT32_MAX)) { return negative ? CMinusInfinity : CInfinity; } - if (RB_UNLIKELY(exponent < INT32_MIN)) { + if (RB_UNLIKELY(exponent <= INT32_MIN)) { return rb_float_new(negative ? -0.0 : 0.0); } @@ -1514,7 +1514,7 @@ static inline VALUE json_parse_number(JSON_ParserState *state, JSON_ParserConfig } if (RB_UNLIKELY(exponent_digits >= 20 || abs_exponent > (uint64_t)INT64_MAX)) { - exponent = negative_exponent ? INT64_MIN : INT64_MAX; + exponent = negative_exponent ? INT32_MIN : INT32_MAX; } else { exponent = negative_exponent ? -(int64_t)abs_exponent : (int64_t)abs_exponent; } diff --git a/java/src/json/ext/Parser.java b/java/src/json/ext/Parser.java index 88bc054ef..6fa5d4383 100644 --- a/java/src/json/ext/Parser.java +++ b/java/src/json/ext/Parser.java @@ -634,7 +634,7 @@ private IRubyObject parseNumber(int numberStart, byte first, boolean negative) { } if (exponent_digits >= 20 || Long.compareUnsigned(abs_exponent, Long.MAX_VALUE) > 0) { - exponent = negative_exponent ? Long.MIN_VALUE : Long.MAX_VALUE; + exponent = negative_exponent ? Integer.MIN_VALUE : Integer.MAX_VALUE; } else { exponent = negative_exponent ? -abs_exponent : abs_exponent; } @@ -655,8 +655,8 @@ private IRubyObject parseNumber(int numberStart, byte first, boolean negative) { IRubyObject decodeFloat(ThreadContext context, long mantissa, int mantissa_digits, long exponent, boolean negative, int start) { if (config.decimalClass != null) return config.decimalFactory.apply(context, absSubSequence(start, cursor)); - if (exponent > Integer.MAX_VALUE) return getConstant(negative ? CONST_MINUS_INFINITY : CONST_INFINITY); - if (exponent < Integer.MIN_VALUE) return RubyFloat.newFloat(context.runtime, negative ? -0.0 : 0.0); + if (exponent >= Integer.MAX_VALUE) return getConstant(negative ? CONST_MINUS_INFINITY : CONST_INFINITY); + if (exponent <= Integer.MIN_VALUE) return RubyFloat.newFloat(context.runtime, negative ? -0.0 : 0.0); // Ryu has rounding issues with subnormals around 1e-310 (< 2.225e-308) if (mantissa_digits > 17 || mantissa_digits + exponent < -307) { diff --git a/test/json/json_parser_test.rb b/test/json/json_parser_test.rb index 75e99904d..47d84b398 100644 --- a/test/json/json_parser_test.rb +++ b/test/json/json_parser_test.rb @@ -147,6 +147,12 @@ def test_parse_numbers assert_raise(ParserError) { parse('-Infinity') } assert_equal(-1.0/0, parse('-Infinity', allow_nan: true)) capture_output { assert_equal(Float::INFINITY, parse("23456789012E666")) } + + assert_parse_float "1.5e-99999999999999999999" + assert_parse_float "1.5e-9223372036854775808" + assert_parse_float "0.0e-99999999999999999999" + assert_parse_float "-1.5e-99999999999999999999" + assert_parse_float "123.456e-18446744073709551615" end INTEGER_FAST_PATH_BOUNDARIES = [ @@ -1084,6 +1090,10 @@ def encode(*) private + def assert_parse_float(float_str) + assert_equal Float(float_str), JSON.parse(float_str) + end + def assert_equal_float(expected, actual, delta = 1e-2) Array === expected and expected = expected.first Array === actual and actual = actual.first