Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[fix](decimal) fix undefined behaviour of divide by zero when cast string to decimal #26792

Merged
merged 2 commits into from
Nov 11, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
improve
  • Loading branch information
jacktengg committed Nov 10, 2023
commit db46a24688ff6875c9859157e3792c5a88843581
18 changes: 5 additions & 13 deletions be/src/util/string_parser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -571,9 +571,9 @@ inline int StringParser::StringParseTraits<__int128>::max_ascii_len() {
template <PrimitiveType P, typename T>
T StringParser::string_to_decimal(const char* s, int len, int type_precision, int type_scale,
ParseResult* result) {
static_assert(std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> ||
std::is_same_v<T, __int128>,
"Cast string to decimal only support target type int32_t, int64_t or __int128.");
static_assert(
std::is_same_v<T, int32_t> || std::is_same_v<T, int64_t> || std::is_same_v<T, __int128>,
"Cast string to decimal only support target type int32_t, int64_t or __int128.");
// Special cases:
// 1) '' == Fail, an empty string fails to parse.
// 2) ' # ' == #, leading and trailing white space is ignored.
Expand Down Expand Up @@ -673,11 +673,7 @@ T StringParser::string_to_decimal(const char* s, int len, int type_precision, in
return 0;
}
*result = StringParser::PARSE_SUCCESS;
if constexpr (std::is_same_v<T, vectorized::Int128I>) {
value *= get_scale_multiplier<__int128>(type_scale - scale);
} else {
value *= get_scale_multiplier<T>(type_scale - scale);
}
value *= get_scale_multiplier<T>(type_scale - scale);

return is_negative ? T(-value) : T(value);
}
Expand Down Expand Up @@ -810,11 +806,7 @@ T StringParser::string_to_decimal(const char* s, int len, int type_precision, in
}

if (type_scale > scale) {
if constexpr (std::is_same_v<T, vectorized::Int128I>) {
value *= get_scale_multiplier<__int128>(type_scale - scale);
} else {
value *= get_scale_multiplier<T>(type_scale - scale);
}
value *= get_scale_multiplier<T>(type_scale - scale);
}

return is_negative ? T(-value) : T(value);
Expand Down
171 changes: 73 additions & 98 deletions be/src/vec/common/int_exp.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,110 +66,85 @@ inline uint64_t int_exp10(int x) {

namespace common {

constexpr inline int exp10_i32(int x)
{
if (x < 0)
return 0;
if (x > 9)
return std::numeric_limits<int>::max();

constexpr int values[] =
{
1,
10,
100,
1000,
10000,
100000,
1000000,
10000000,
100000000,
1000000000
};
constexpr inline int exp10_i32(int x) {
if (x < 0) return 0;
if (x > 9) return std::numeric_limits<int>::max();

constexpr int values[] = {1, 10, 100, 1000, 10000,
100000, 1000000, 10000000, 100000000, 1000000000};
return values[x];
}

constexpr inline int64_t exp10_i64(int x)
{
if (x < 0)
return 0;
if (x > 18)
return std::numeric_limits<int64_t>::max();

constexpr int64_t values[] =
{
1LL,
10LL,
100LL,
1000LL,
10000LL,
100000LL,
1000000LL,
10000000LL,
100000000LL,
1000000000LL,
10000000000LL,
100000000000LL,
1000000000000LL,
10000000000000LL,
100000000000000LL,
1000000000000000LL,
10000000000000000LL,
100000000000000000LL,
1000000000000000000LL
};
constexpr inline int64_t exp10_i64(int x) {
if (x < 0) return 0;
if (x > 18) return std::numeric_limits<int64_t>::max();

constexpr int64_t values[] = {1LL,
10LL,
100LL,
1000LL,
10000LL,
100000LL,
1000000LL,
10000000LL,
100000000LL,
1000000000LL,
10000000000LL,
100000000000LL,
1000000000000LL,
10000000000000LL,
100000000000000LL,
1000000000000000LL,
10000000000000000LL,
100000000000000000LL,
1000000000000000000LL};
return values[x];
}

constexpr inline __int128 exp10_i128(int x)
{
if (x < 0)
return 0;
if (x > 38)
return std::numeric_limits<__int128>::max();

constexpr __int128 values[] =
{
static_cast<__int128>(1LL),
static_cast<__int128>(10LL),
static_cast<__int128>(100LL),
static_cast<__int128>(1000LL),
static_cast<__int128>(10000LL),
static_cast<__int128>(100000LL),
static_cast<__int128>(1000000LL),
static_cast<__int128>(10000000LL),
static_cast<__int128>(100000000LL),
static_cast<__int128>(1000000000LL),
static_cast<__int128>(10000000000LL),
static_cast<__int128>(100000000000LL),
static_cast<__int128>(1000000000000LL),
static_cast<__int128>(10000000000000LL),
static_cast<__int128>(100000000000000LL),
static_cast<__int128>(1000000000000000LL),
static_cast<__int128>(10000000000000000LL),
static_cast<__int128>(100000000000000000LL),
static_cast<__int128>(1000000000000000000LL),
static_cast<__int128>(1000000000000000000LL) * 10LL,
static_cast<__int128>(1000000000000000000LL) * 100LL,
static_cast<__int128>(1000000000000000000LL) * 1000LL,
static_cast<__int128>(1000000000000000000LL) * 10000LL,
static_cast<__int128>(1000000000000000000LL) * 100000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 10LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 100LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 1000LL
};
constexpr inline __int128 exp10_i128(int x) {
if (x < 0) return 0;
if (x > 38) return std::numeric_limits<__int128>::max();

constexpr __int128 values[] = {
static_cast<__int128>(1LL),
static_cast<__int128>(10LL),
static_cast<__int128>(100LL),
static_cast<__int128>(1000LL),
static_cast<__int128>(10000LL),
static_cast<__int128>(100000LL),
static_cast<__int128>(1000000LL),
static_cast<__int128>(10000000LL),
static_cast<__int128>(100000000LL),
static_cast<__int128>(1000000000LL),
static_cast<__int128>(10000000000LL),
static_cast<__int128>(100000000000LL),
static_cast<__int128>(1000000000000LL),
static_cast<__int128>(10000000000000LL),
static_cast<__int128>(100000000000000LL),
static_cast<__int128>(1000000000000000LL),
static_cast<__int128>(10000000000000000LL),
static_cast<__int128>(100000000000000000LL),
static_cast<__int128>(1000000000000000000LL),
static_cast<__int128>(1000000000000000000LL) * 10LL,
static_cast<__int128>(1000000000000000000LL) * 100LL,
static_cast<__int128>(1000000000000000000LL) * 1000LL,
static_cast<__int128>(1000000000000000000LL) * 10000LL,
static_cast<__int128>(1000000000000000000LL) * 100000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 1000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 10000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 10LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 100LL,
static_cast<__int128>(1000000000000000000LL) * 100000000000000000LL * 1000LL};
return values[x];
}

Expand Down