Fixed UB (requires performance testing) #3569

This commit is contained in:
Alexey Milovidov 2018-12-26 03:31:51 +03:00
parent b1b1c676c9
commit ee953b4653
4 changed files with 13 additions and 25 deletions

View File

@ -254,7 +254,7 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
bool negative = false;
x = 0;
std::make_unsigned_t<T> res = 0;
if (buf.eof())
{
if constexpr (throw_exception)
@ -290,22 +290,17 @@ ReturnType readIntTextImpl(T & x, ReadBuffer & buf)
case '7': [[fallthrough]];
case '8': [[fallthrough]];
case '9':
x *= 10;
x += *buf.position() - '0';
res *= 10;
res += *buf.position() - '0';
break;
default:
if (negative)
x = -x;
x = negative ? -res : res;
return ReturnType(true);
}
++buf.position();
}
/// NOTE Signed integer overflow is undefined behaviour. Consider we have '128' that is parsed as Int8 and overflowed.
/// We are happy if it is overflowed to -128 and then 'x = -x' does nothing. But UBSan will warn.
if (negative)
x = -x;
x = negative ? -res : res;
return ReturnType(true);
}
@ -331,7 +326,7 @@ template <typename T, bool throw_on_error = true>
void readIntTextUnsafe(T & x, ReadBuffer & buf)
{
bool negative = false;
x = 0;
std::make_unsigned_t<T> res = 0;
auto on_error = []
{
@ -365,8 +360,8 @@ void readIntTextUnsafe(T & x, ReadBuffer & buf)
if ((*buf.position() & 0xF0) == 0x30) /// It makes sense to have this condition inside loop.
{
x *= 10;
x += *buf.position() & 0x0F;
res *= 10;
res += *buf.position() & 0x0F;
++buf.position();
}
else
@ -374,8 +369,7 @@ void readIntTextUnsafe(T & x, ReadBuffer & buf)
}
/// See note about undefined behaviour above.
if (std::is_signed_v<T> && negative)
x = -x;
x = std::is_signed_v<T> && negative ? -res : res;
}
template <typename T>

View File

@ -185,7 +185,6 @@ namespace detail
writeUIntText(static_cast<std::make_unsigned_t<T>>(x), buf);
}
#if 1
inline void writeSIntText(__int128 x, WriteBuffer & buf)
{
static const __int128 min_int128 = __int128(0x8000000000000000ll) << 64;
@ -204,7 +203,6 @@ namespace detail
writeUIntText(static_cast<unsigned __int128>(x), buf);
}
#endif
}

View File

@ -56,7 +56,7 @@ static UInt64 readUIntText(const char * buf, const char * end)
static Int64 readIntText(const char * buf, const char * end)
{
bool negative = false;
Int64 x = 0;
UInt64 x = 0;
if (buf == end)
throw JSONException("JSON: cannot parse signed integer: unexpected end of data.");
@ -90,10 +90,8 @@ static Int64 readIntText(const char * buf, const char * end)
}
++buf;
}
if (negative)
x = -x;
return x;
return negative ? -x : x;
}

View File

@ -44,7 +44,7 @@ UInt64 Value::readUIntText(const char * buf, size_t length) const
Int64 Value::readIntText(const char * buf, size_t length) const
{
bool negative = false;
Int64 x = 0;
UInt64 x = 0;
const char * end = buf + length;
while (buf != end)
@ -74,10 +74,8 @@ Int64 Value::readIntText(const char * buf, size_t length) const
}
++buf;
}
if (negative)
x = -x;
return x;
return negative ? -x : x;
}