diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 603fd76..238a3c5 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -573,8 +573,6 @@ Reader::decodeNumber( Token &token ) Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt) : Value::maxLargestUInt; Value::LargestUInt threshold = maxIntegerValue / 10; - Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 ); - assert( lastDigitThreshold >=0 && lastDigitThreshold <= 9 ); Value::LargestUInt value = 0; while ( current < token.end_ ) { @@ -584,10 +582,13 @@ Reader::decodeNumber( Token &token ) Value::UInt digit(c - '0'); if ( value >= threshold ) { - // If the current digit is not the last one, or if it is - // greater than the last digit of the maximum integer value, - // the parse the number as a double. - if ( current != token.end_ || digit > lastDigitThreshold ) + // We've hit or exceeded the max value divided by 10 (rounded down). If + // a) we've only just touched the limit, b) this is the last digit, and + // c) it's small enough to fit in that rounding delta, we're okay. + // Otherwise treat this number as a double to avoid overflow. + if (value > threshold || + current != token.end_ || + digit > maxIntegerValue % 10) { return decodeDouble( token ); } diff --git a/test/data/test_real_09.expected b/test/data/test_real_09.expected index ee2e5ef..6da815e 100644 --- a/test/data/test_real_09.expected +++ b/test/data/test_real_09.expected @@ -1 +1 @@ -.=19000000000000000001 +.=1.9e+19 diff --git a/test/data/test_real_11.expected b/test/data/test_real_11.expected index 83d3cc3..17f4187 100644 --- a/test/data/test_real_11.expected +++ b/test/data/test_real_11.expected @@ -1 +1 @@ -.=-9300000000000000001 +.=-9.3e+18 diff --git a/test/data/test_real_12.expected b/test/data/test_real_12.expected new file mode 100644 index 0000000..a000319 --- /dev/null +++ b/test/data/test_real_12.expected @@ -0,0 +1 @@ +.=1.844674407370955e+19 diff --git a/test/data/test_real_12.json b/test/data/test_real_12.json new file mode 100644 index 0000000..0a13eed --- /dev/null +++ b/test/data/test_real_12.json @@ -0,0 +1,2 @@ +// 2^64 -> switch to double. +18446744073709551616