mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 09:32:06 +00:00
Fix potential overflow in integer division #12119
This commit is contained in:
parent
c696354dd4
commit
73a5c38398
@ -26,12 +26,11 @@ struct DivideIntegralByConstantImpl
|
||||
|
||||
static NO_INLINE void vectorConstant(const A * __restrict a_pos, B b, ResultType * __restrict c_pos, size_t size)
|
||||
{
|
||||
if (unlikely(b == 0))
|
||||
throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
/// Division by -1. By the way, we avoid FPE by division of the largest negative number by -1.
|
||||
/// And signed integer overflow is well defined in C++20.
|
||||
if (unlikely(is_signed_v<B> && b == -1))
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
@ -39,8 +38,20 @@ struct DivideIntegralByConstantImpl
|
||||
return;
|
||||
}
|
||||
|
||||
/// Division with too large divisor.
|
||||
if (unlikely(b > std::numeric_limits<A>::max()
|
||||
|| (std::is_signed_v<A> && std::is_signed_v<B> && b < std::numeric_limits<A>::lowest())))
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
c_pos[i] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
if (unlikely(static_cast<A>(b) == 0))
|
||||
throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION);
|
||||
|
||||
libdivide::divider<A> divider(b);
|
||||
|
||||
const A * a_end = a_pos + size;
|
||||
|
@ -27,12 +27,10 @@ struct ModuloByConstantImpl
|
||||
|
||||
static NO_INLINE void vectorConstant(const A * __restrict src, B b, ResultType * __restrict dst, size_t size)
|
||||
{
|
||||
if (unlikely(b == 0))
|
||||
throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION);
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
/// Modulo with too small divisor.
|
||||
if (unlikely((std::is_signed_v<B> && b == -1) || b == 1))
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
@ -40,8 +38,20 @@ struct ModuloByConstantImpl
|
||||
return;
|
||||
}
|
||||
|
||||
/// Modulo with too large divisor.
|
||||
if (unlikely(b > std::numeric_limits<A>::max()
|
||||
|| (std::is_signed_v<A> && std::is_signed_v<B> && b < std::numeric_limits<A>::lowest())))
|
||||
{
|
||||
for (size_t i = 0; i < size; ++i)
|
||||
dst[i] = src[i];
|
||||
return;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
if (unlikely(static_cast<A>(b) == 0))
|
||||
throw Exception("Division by zero", ErrorCodes::ILLEGAL_DIVISION);
|
||||
|
||||
libdivide::divider<A> divider(b);
|
||||
|
||||
/// Here we failed to make the SSE variant from libdivide give an advantage.
|
||||
|
@ -21,6 +21,8 @@ IColumn::Selector createBlockSelector(
|
||||
const std::vector<UInt64> & slots)
|
||||
{
|
||||
const auto total_weight = slots.size();
|
||||
assert(total_weight != 0);
|
||||
|
||||
size_t num_rows = column.size();
|
||||
IColumn::Selector selector(num_rows);
|
||||
|
||||
|
@ -15,7 +15,6 @@
|
||||
#include <DataStreams/ConvertingBlockInputStream.h>
|
||||
#include <DataStreams/OneBlockInputStream.h>
|
||||
#include <Interpreters/InterpreterInsertQuery.h>
|
||||
#include <Interpreters/createBlockSelector.h>
|
||||
#include <Interpreters/ExpressionActions.h>
|
||||
#include <Interpreters/Context.h>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user