Merge pull request #12005 from ClickHouse/fix-div-nontrivial-fpe

Fix potential FPE.
This commit is contained in:
alexey-milovidov 2020-06-28 16:16:26 +03:00 committed by GitHub
commit d867dd8a65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 18 additions and 4 deletions

View File

@ -44,6 +44,13 @@ inline bool divisionLeadsToFPE(A a, B b)
return false; return false;
} }
template <typename A, typename B>
inline auto checkedDivision(A a, B b)
{
throwIfDivisionLeadsToFPE(a, b);
return a / b;
}
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -56,14 +63,13 @@ struct DivideIntegralImpl
template <typename Result = ResultType> template <typename Result = ResultType>
static inline Result apply(A a, B b) static inline Result apply(A a, B b)
{ {
throwIfDivisionLeadsToFPE(a, b);
/// Otherwise overflow may occur due to integer promotion. Example: int8_t(-1) / uint64_t(2). /// Otherwise overflow may occur due to integer promotion. Example: int8_t(-1) / uint64_t(2).
/// NOTE: overflow is still possible when dividing large signed number to large unsigned number or vice-versa. But it's less harmful. /// NOTE: overflow is still possible when dividing large signed number to large unsigned number or vice-versa. But it's less harmful.
if constexpr (is_integral_v<A> && is_integral_v<B> && (is_signed_v<A> || is_signed_v<B>)) if constexpr (is_integral_v<A> && is_integral_v<B> && (is_signed_v<A> || is_signed_v<B>))
return std::make_signed_t<A>(a) / std::make_signed_t<B>(b); return checkedDivision(std::make_signed_t<A>(a),
sizeof(A) > sizeof(B) ? std::make_signed_t<A>(b) : std::make_signed_t<B>(b));
else else
return a / b; return checkedDivision(a, b);
} }
#if USE_EMBEDDED_COMPILER #if USE_EMBEDDED_COMPILER

View File

@ -0,0 +1,3 @@
-36170086419038336
-140739635871744
-2147483648

View File

@ -0,0 +1,5 @@
select intDiv(-9223372036854775808, 255);
select intDiv(-9223372036854775808, 65535);
select intDiv(-9223372036854775808, 4294967295);
select intDiv(-9223372036854775808, 18446744073709551615); -- { serverError 153 }
select intDiv(-9223372036854775808, -1); -- { serverError 153 }