Issue #633: Fix issue with maxInt

This patch is a minor fix to Json::OurReader to properly check against
maxLargestInt, not maxInt. Some cleanup in the decodeNumber method is
included.
This commit is contained in:
Jordan Bayles 2019-06-28 09:34:16 -07:00
parent ddc9e0fcd7
commit 44bc38f0a1

View File

@ -1547,36 +1547,46 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
bool isNegative = *current == '-'; bool isNegative = *current == '-';
if (isNegative) if (isNegative)
++current; ++current;
// TODO: Help the compiler do the div and mod at compile time or get rid of
// them. // TODO(issue #960): Change to constexpr
Value::LargestUInt maxIntegerValue = static const auto positive_threshold = Value::maxLargestUInt / 10;
isNegative ? Value::LargestUInt(Value::minLargestInt) static const auto positive_last_digit = Value::maxLargestUInt % 10;
: Value::maxLargestUInt; static const auto negative_threshold =
Value::LargestUInt threshold = maxIntegerValue / 10; Value::LargestUInt(Value::minLargestInt) / 10;
static const auto negative_last_digit =
Value::LargestUInt(Value::minLargestInt) % 10;
const auto threshold = isNegative ? negative_threshold : positive_threshold;
const auto last_digit =
isNegative ? negative_last_digit : positive_last_digit;
Value::LargestUInt value = 0; Value::LargestUInt value = 0;
while (current < token.end_) { while (current < token.end_) {
Char c = *current++; Char c = *current++;
if (c < '0' || c > '9') if (c < '0' || c > '9')
return decodeDouble(token, decoded); return decodeDouble(token, decoded);
auto digit(static_cast<Value::UInt>(c - '0'));
const auto digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) { if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If // 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 // a) we've only just touched the limit, meaing value == threshold,
// b) this is the last digit, or
// c) it's small enough to fit in that rounding delta, we're okay. // c) it's small enough to fit in that rounding delta, we're okay.
// Otherwise treat this number as a double to avoid overflow. // Otherwise treat this number as a double to avoid overflow.
if (value > threshold || current != token.end_ || if (value > threshold || current != token.end_ || digit > last_digit) {
digit > maxIntegerValue % 10) {
return decodeDouble(token, decoded); return decodeDouble(token, decoded);
} }
} }
value = value * 10 + digit; value = value * 10 + digit;
} }
if (isNegative) if (isNegative)
decoded = -Value::LargestInt(value); decoded = -Value::LargestInt(value);
else if (value <= Value::LargestUInt(Value::maxInt)) else if (value <= Value::LargestUInt(Value::maxLargestInt))
decoded = Value::LargestInt(value); decoded = Value::LargestInt(value);
else else
decoded = value; decoded = value;
return true; return true;
} }