mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-08-05 11:06:36 -04:00
json_value.cpp bug in the edges of uint/int
Fixing bug of sending a number that is a bit bigger than max<uint64_t> it returns 0: https://stackoverflow.com/questions/77261400/jsoncpp-do-not-protect-from-uint64-overflow-and-have-weird-behavior/77261716#77261716
This commit is contained in:
parent
e040b981d3
commit
8093d8c47c
@ -88,7 +88,7 @@ static inline bool InRange(double d, T min, U max) {
|
|||||||
// The casts can lose precision, but we are looking only for
|
// The casts can lose precision, but we are looking only for
|
||||||
// an approximate range. Might fail on edge cases though. ~cdunn
|
// an approximate range. Might fail on edge cases though. ~cdunn
|
||||||
return d >= static_cast<double>(min) && d <= static_cast<double>(max) &&
|
return d >= static_cast<double>(min) && d <= static_cast<double>(max) &&
|
||||||
!(static_cast<T>(d) != min || d == min);
|
!(static_cast<U>(d) == min && d != static_cast<double>(min));
|
||||||
}
|
}
|
||||||
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
static inline double integerToDouble(Json::UInt64 value) {
|
static inline double integerToDouble(Json::UInt64 value) {
|
||||||
@ -103,7 +103,7 @@ template <typename T> static inline double integerToDouble(T value) {
|
|||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
static inline bool InRange(double d, T min, U max) {
|
static inline bool InRange(double d, T min, U max) {
|
||||||
return d >= integerToDouble(min) && d <= integerToDouble(max) &&
|
return d >= integerToDouble(min) && d <= integerToDouble(max) &&
|
||||||
!(static_cast<T>(d) == min || d != integerToDouble(min));
|
!(static_cast<U>(d) == min && d != integerToDouble(min));
|
||||||
}
|
}
|
||||||
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
|
|
||||||
@ -707,6 +707,10 @@ Value::Int64 Value::asInt64() const {
|
|||||||
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
|
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
|
||||||
return Int64(value_.uint_);
|
return Int64(value_.uint_);
|
||||||
case realValue:
|
case realValue:
|
||||||
|
// If the double value is in proximity to minInt64, it will be rounded to minInt64.
|
||||||
|
// The correct value in this scenario is indeterminable
|
||||||
|
JSON_ASSERT_MESSAGE(value_.real_ != minInt64,
|
||||||
|
"Double value is minInt64, precise value cannot be determined");
|
||||||
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
|
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
|
||||||
"double out of Int64 range");
|
"double out of Int64 range");
|
||||||
return Int64(value_.real_);
|
return Int64(value_.real_);
|
||||||
@ -1310,7 +1314,10 @@ bool Value::isInt64() const {
|
|||||||
// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
|
// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
|
||||||
// double, so double(maxInt64) will be rounded up to 2^63. Therefore we
|
// double, so double(maxInt64) will be rounded up to 2^63. Therefore we
|
||||||
// require the value to be strictly less than the limit.
|
// require the value to be strictly less than the limit.
|
||||||
return value_.real_ >= double(minInt64) &&
|
// minInt64 is -2^63 which can be represented as a double, but since double values in its proximity are also
|
||||||
|
// rounded to -2^63, we require the value to be strictly greater than the limit to avoid returning
|
||||||
|
// 'true' for values that are not in the range
|
||||||
|
return value_.real_ > double(minInt64) &&
|
||||||
value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
|
value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1349,7 +1356,10 @@ bool Value::isIntegral() const {
|
|||||||
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
|
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
|
||||||
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
|
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
|
||||||
// require the value to be strictly less than the limit.
|
// require the value to be strictly less than the limit.
|
||||||
return value_.real_ >= double(minInt64) &&
|
// minInt64 is -2^63 which can be represented as a double, but since double values in its proximity are also
|
||||||
|
// rounded to -2^63, we require the value to be strictly greater than the limit to avoid returning
|
||||||
|
// 'true' for values that are not in the range
|
||||||
|
return value_.real_ > double(minInt64) &&
|
||||||
value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
|
value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
|
||||||
#else
|
#else
|
||||||
return value_.real_ >= minInt && value_.real_ <= maxUInt &&
|
return value_.real_ >= minInt && value_.real_ <= maxUInt &&
|
||||||
|
Loading…
x
Reference in New Issue
Block a user