mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Merge pull request #10511 from ClickHouse/fix-ubsan-datetime64
Fixed UBSan for DateTime64; added a test
This commit is contained in:
commit
0a9bcae0ed
@ -2,15 +2,20 @@
|
||||
// Moved Decimal-related functions out from Core/Types.h to reduce compilation time.
|
||||
|
||||
#include <Core/Types.h>
|
||||
#include <Common/intExp.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <common/arithmeticOverflow.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
class DateLUTImpl;
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int DECIMAL_OVERFLOW;
|
||||
}
|
||||
|
||||
namespace DecimalUtils
|
||||
{
|
||||
|
||||
@ -37,22 +42,26 @@ struct DecimalComponents
|
||||
};
|
||||
|
||||
/** Make a decimal value from whole and fractional components with given scale multiplier.
|
||||
* where scale_multiplier = scaleMultiplier<T>(scale)
|
||||
* this is to reduce number of calls to scaleMultiplier when scale is known.
|
||||
*
|
||||
* Sign of `whole` controls sign of result: negative whole => negative result, positive whole => positive result.
|
||||
* Sign of `fractional` is expected to be positive, otherwise result is undefined.
|
||||
* If `scale` is to big (scale > maxPrecision<DecimalType::NativeType>), result is undefined.
|
||||
*/
|
||||
* where scale_multiplier = scaleMultiplier<T>(scale)
|
||||
* this is to reduce number of calls to scaleMultiplier when scale is known.
|
||||
*
|
||||
* Sign of `whole` controls sign of result: negative whole => negative result, positive whole => positive result.
|
||||
* Sign of `fractional` is expected to be positive, otherwise result is undefined.
|
||||
* If `scale` is to big (scale > maxPrecision<DecimalType::NativeType>), result is undefined.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalType decimalFromComponentsWithMultiplier(const typename DecimalType::NativeType & whole,
|
||||
const typename DecimalType::NativeType & fractional,
|
||||
typename DecimalType::NativeType scale_multiplier)
|
||||
const typename DecimalType::NativeType & fractional,
|
||||
typename DecimalType::NativeType scale_multiplier)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
const auto fractional_sign = whole < 0 ? -1 : 1;
|
||||
|
||||
const T value = whole * scale_multiplier + fractional_sign * (fractional % scale_multiplier);
|
||||
T whole_scaled = 0;
|
||||
if (common::mulOverflow(whole, scale_multiplier, whole_scaled))
|
||||
throw Exception("Decimal math overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
|
||||
const T value = whole_scaled + fractional_sign * (fractional % scale_multiplier);
|
||||
return DecimalType(value);
|
||||
}
|
||||
|
||||
@ -61,7 +70,8 @@ DecimalType decimalFromComponentsWithMultiplier(const typename DecimalType::Nati
|
||||
* @see `decimalFromComponentsWithMultiplier` for details.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalType decimalFromComponents(const typename DecimalType::NativeType & whole, const typename DecimalType::NativeType & fractional, UInt32 scale)
|
||||
DecimalType decimalFromComponents(
|
||||
const typename DecimalType::NativeType & whole, const typename DecimalType::NativeType & fractional, UInt32 scale)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
|
||||
@ -72,7 +82,8 @@ DecimalType decimalFromComponents(const typename DecimalType::NativeType & whole
|
||||
* @see `decimalFromComponentsWithMultiplier` for details.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalType decimalFromComponents(const DecimalComponents<typename DecimalType::NativeType> & components, UInt32 scale)
|
||||
DecimalType decimalFromComponents(
|
||||
const DecimalComponents<typename DecimalType::NativeType> & components, UInt32 scale)
|
||||
{
|
||||
return decimalFromComponents<DecimalType>(components.whole, components.fractional, scale);
|
||||
}
|
||||
@ -81,7 +92,8 @@ DecimalType decimalFromComponents(const DecimalComponents<typename DecimalType::
|
||||
* This is an optimization to reduce number of calls to scaleMultiplier on known scale.
|
||||
*/
|
||||
template <typename DecimalType>
|
||||
DecimalComponents<typename DecimalType::NativeType> splitWithScaleMultiplier(const DecimalType & decimal, typename DecimalType::NativeType scale_multiplier)
|
||||
DecimalComponents<typename DecimalType::NativeType> splitWithScaleMultiplier(
|
||||
const DecimalType & decimal, typename DecimalType::NativeType scale_multiplier)
|
||||
{
|
||||
using T = typename DecimalType::NativeType;
|
||||
const auto whole = decimal.value / scale_multiplier;
|
||||
|
@ -0,0 +1 @@
|
||||
29
|
2
tests/queries/0_stateless/01259_datetime64_ubsan.sql
Normal file
2
tests/queries/0_stateless/01259_datetime64_ubsan.sql
Normal file
@ -0,0 +1,2 @@
|
||||
select now64(10); -- { serverError 407 }
|
||||
select length(toString(now64(9)));
|
Loading…
Reference in New Issue
Block a user