mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 23:52:03 +00:00
Merge pull request #12005 from ClickHouse/fix-div-nontrivial-fpe
Fix potential FPE.
This commit is contained in:
commit
d867dd8a65
@ -44,6 +44,13 @@ inline bool divisionLeadsToFPE(A a, B b)
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename A, typename B>
|
||||
inline auto checkedDivision(A a, B b)
|
||||
{
|
||||
throwIfDivisionLeadsToFPE(a, b);
|
||||
return a / b;
|
||||
}
|
||||
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
@ -56,14 +63,13 @@ struct DivideIntegralImpl
|
||||
template <typename Result = ResultType>
|
||||
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).
|
||||
/// 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>))
|
||||
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
|
||||
return a / b;
|
||||
return checkedDivision(a, b);
|
||||
}
|
||||
|
||||
#if USE_EMBEDDED_COMPILER
|
||||
|
@ -0,0 +1,3 @@
|
||||
-36170086419038336
|
||||
-140739635871744
|
||||
-2147483648
|
@ -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 }
|
Loading…
Reference in New Issue
Block a user