1
0
mirror of https://github.com/nlohmann/json synced 2024-12-05 01:30:07 +00:00

Improved overflow detection; removed debugging output statements.

This commit is contained in:
Alex Astashyn 2016-12-03 22:54:36 -05:00
parent 6b78b5c2be
commit 4eafaab816
2 changed files with 48 additions and 46 deletions

View File

@ -9223,14 +9223,6 @@ basic_json_parser_66:
value = -0.0; value = -0.0;
} }
if(!ok) {
std::cerr << "data:" << data
<< " token:" << std::string(m_start, len)
<< " value:" << value
<< " len:" << len
<< " parsed_len:" << (endptr - data) << std::endl;
}
return ok; return ok;
} }
@ -9252,31 +9244,40 @@ basic_json_parser_66:
++beg; // skip the leading sign ++beg; // skip the leading sign
} }
// using unsigned accumulator x because the signed
// type can't hold absolute value of largest
// negative value of this type, so overflow detection
// becomes problematic.
using unsigned_T = typename std::make_unsigned<T>::type;
unsigned_T x = 0;
bool valid = beg < end // must have some digits; bool valid = beg < end // must have some digits;
and ( T(-1) < 0 // type must be signed and ( T(-1) < 0 // type must be signed
or !is_negative); // if value is negative or !is_negative); // if value is negative
value = 0;
while(beg < end and valid) { while(beg < end and valid) {
const uint8_t c = static_cast<uint8_t>(*beg - '0'); const uint8_t c = static_cast<uint8_t>(*beg - '0');
const T upd_value = value * 10 + c; const unsigned_T upd_x = x * 10 + c;
valid &= value <= std::numeric_limits<T>::max() / 10
and value <= upd_value // did not overflow using lim_T = std::numeric_limits<T>;
and c < 10; // char was digit constexpr unsigned_T thr1 = lim_T::max() / 10;
value = upd_value; valid &= c < 10 // char was digit
and x <= thr1 // multiplication did not overflow
and x <= upd_x; // addition did not overflow.
// note that x <= upd_x alone can't detect overflow since
// we're not just adding a value of decltype(x) but
// also multiplying by 10
x = upd_x;
++beg; ++beg;
} }
if(is_negative) { value = static_cast<T>(is_negative ? 0 - x : x);
value = 0 - value;
}
if(!valid) { // the final check to make sure the value did not roll over
std::cerr << " token:" << std::string(m_start, m_end) // into positives is for edge cases, e.g. -2^63
<< std::endl; return valid && (is_negative == (value < 0));
}
return valid;
} }
}; };

View File

@ -8372,14 +8372,6 @@ class basic_json
value = -0.0; value = -0.0;
} }
if(!ok) {
std::cerr << "data:" << data
<< " token:" << std::string(m_start, len)
<< " value:" << value
<< " len:" << len
<< " parsed_len:" << (endptr - data) << std::endl;
}
return ok; return ok;
} }
@ -8401,31 +8393,40 @@ class basic_json
++beg; // skip the leading sign ++beg; // skip the leading sign
} }
// using unsigned accumulator x because the signed
// type can't hold absolute value of largest
// negative value of this type, so overflow detection
// becomes problematic.
using unsigned_T = typename std::make_unsigned<T>::type;
unsigned_T x = 0;
bool valid = beg < end // must have some digits; bool valid = beg < end // must have some digits;
and ( T(-1) < 0 // type must be signed and ( T(-1) < 0 // type must be signed
or !is_negative); // if value is negative or !is_negative); // if value is negative
value = 0;
while(beg < end and valid) { while(beg < end and valid) {
const uint8_t c = static_cast<uint8_t>(*beg - '0'); const uint8_t c = static_cast<uint8_t>(*beg - '0');
const T upd_value = value * 10 + c; const unsigned_T upd_x = x * 10 + c;
valid &= value <= std::numeric_limits<T>::max() / 10
and value <= upd_value // did not overflow using lim_T = std::numeric_limits<T>;
and c < 10; // char was digit constexpr unsigned_T thr1 = lim_T::max() / 10;
value = upd_value; valid &= c < 10 // char was digit
and x <= thr1 // multiplication did not overflow
and x <= upd_x; // addition did not overflow.
// note that x <= upd_x alone can't detect overflow since
// we're not just adding a value of decltype(x) but
// also multiplying by 10
x = upd_x;
++beg; ++beg;
} }
if(is_negative) { value = static_cast<T>(is_negative ? 0 - x : x);
value = 0 - value;
}
if(!valid) { // the final check to make sure the value did not roll over
std::cerr << " token:" << std::string(m_start, m_end) // into positives is for edge cases, e.g. -2^63
<< std::endl; return valid && (is_negative == (value < 0));
}
return valid;
} }
}; };