Add defense for builtin_clz/builtin_ctz in case that input is zero

This commit is contained in:
obdev
2021-07-18 15:24:13 +08:00
committed by wangzelin.wzl
parent 3a6db0a542
commit 4770dbcdcb
9 changed files with 14 additions and 8 deletions

View File

@ -79,11 +79,13 @@ private:
inline int calc_clz(const uint32_t s) inline int calc_clz(const uint32_t s)
{ {
OB_ASSERT(0 != s);
return __builtin_clz(s); return __builtin_clz(s);
} }
inline int calc_clz(const uint64_t s) inline int calc_clz(const uint64_t s)
{ {
OB_ASSERT(0ULL != s);
return __builtin_clzl(s); return __builtin_clzl(s);
} }

View File

@ -138,6 +138,7 @@ public:
private: private:
static uint64_t calc_shift(uint64_t capacity) static uint64_t calc_shift(uint64_t capacity)
{ {
OB_ASSERT(0ULL != capacity);
return __builtin_clzll(capacity) + 1; return __builtin_clzll(capacity) + 1;
} }
HashNode* locate(uint64_t hash) HashNode* locate(uint64_t hash)

View File

@ -163,6 +163,7 @@ public:
private: private:
static uint64_t calc_n_cond(uint64_t capacity) static uint64_t calc_n_cond(uint64_t capacity)
{ {
OB_ASSERT(0ULL != capacity);
return std::min(1024ULL, 1ULL << (63 - __builtin_clzll(capacity))); return std::min(1024ULL, 1ULL << (63 - __builtin_clzll(capacity)));
} }
uint64_t push_bounded(void* p, uint64_t limit) uint64_t push_bounded(void* p, uint64_t limit)

View File

@ -71,7 +71,7 @@ int32_t parse_string_to_int_array(const char* line, const char del, int32_t* arr
bool is2n(int64_t input); bool is2n(int64_t input);
constexpr int64_t next_pow2(const int64_t x) constexpr int64_t next_pow2(const int64_t x)
{ {
return x ? (1ULL << (8 * sizeof(int64_t) - __builtin_clzll(x - 1))) : 1; return x > 1LL ? (1ULL << (8 * sizeof(int64_t) - __builtin_clzll(x - 1))) : 1LL;
} }
bool all_zero(const char* buffer, const int64_t size); bool all_zero(const char* buffer, const int64_t size);

View File

@ -80,6 +80,7 @@ void ObExprEstimateNdv::llc_estimate_ndv(int64_t& result, const ObString& bitmap
} }
uint64_t ObExprEstimateNdv::llc_leading_zeros(uint64_t value, uint64_t bit_width) uint64_t ObExprEstimateNdv::llc_leading_zeros(uint64_t value, uint64_t bit_width)
{ {
OB_ASSERT(0ULL != value);
return std::min(bit_width, static_cast<uint64_t>(__builtin_clzll(value))); return std::min(bit_width, static_cast<uint64_t>(__builtin_clzll(value)));
} }

View File

@ -126,8 +126,9 @@ public:
typedef bool (*is_type_func)(common::ObObjType type); typedef bool (*is_type_func)(common::ObObjType type);
static constexpr int flag2bit(uint64_t flag) static int flag2bit(uint64_t flag)
{ {
OB_ASSERT(0ULL != flag);
return static_cast<int>(__builtin_ctzll(flag)); return static_cast<int>(__builtin_ctzll(flag));
} }

View File

@ -1561,12 +1561,14 @@ void ObHashJoinOp::calc_cache_aware_partition_count()
int64_t tmp_partition_cnt_per_level = max_partition_count_per_level_; int64_t tmp_partition_cnt_per_level = max_partition_count_per_level_;
if (total_partition_cnt > tmp_partition_cnt_per_level) { if (total_partition_cnt > tmp_partition_cnt_per_level) {
level1_part_count_ = part_count_; level1_part_count_ = part_count_;
OB_ASSERT(0 != level1_part_count_);
level1_bit_ = __builtin_ctz(level1_part_count_); level1_bit_ = __builtin_ctz(level1_part_count_);
level2_part_count_ = total_partition_cnt / level1_part_count_; level2_part_count_ = total_partition_cnt / level1_part_count_;
level2_part_count_ = level2_part_count_ =
level2_part_count_ > tmp_partition_cnt_per_level ? tmp_partition_cnt_per_level : level2_part_count_; level2_part_count_ > tmp_partition_cnt_per_level ? tmp_partition_cnt_per_level : level2_part_count_;
} else { } else {
level1_part_count_ = total_partition_cnt > part_count_ ? total_partition_cnt : part_count_; level1_part_count_ = total_partition_cnt > part_count_ ? total_partition_cnt : part_count_;
OB_ASSERT(0 != level1_part_count_);
level1_bit_ = __builtin_ctz(level1_part_count_); level1_bit_ = __builtin_ctz(level1_part_count_);
} }
LOG_TRACE("partition count", LOG_TRACE("partition count",
@ -2755,6 +2757,7 @@ int ObHashJoinOp::get_next_probe_partition()
} }
} else { } else {
// two level // two level
OB_ASSERT(0 != level2_part_count_);
int64_t level1_part_idx = (cur_full_right_partition_ >> (__builtin_ctz(level2_part_count_))); int64_t level1_part_idx = (cur_full_right_partition_ >> (__builtin_ctz(level2_part_count_)));
if (level1_part_idx < dump_part_count) { if (level1_part_idx < dump_part_count) {
cur_left_hist_ = &part_histograms_[cur_full_right_partition_]; cur_left_hist_ = &part_histograms_[cur_full_right_partition_];

View File

@ -307,6 +307,8 @@ private:
void set_part_count(int64_t part_shift, int64_t level1_part_count, int64_t level2_part_count) void set_part_count(int64_t part_shift, int64_t level1_part_count, int64_t level2_part_count)
{ {
OB_ASSERT(0 != level1_part_count);
OB_ASSERT(0 != level2_part_count);
part_shift_ = part_shift; part_shift_ = part_shift;
level_one_part_count_ = level1_part_count; level_one_part_count_ = level1_part_count;
level_two_part_count_ = level2_part_count; level_two_part_count_ = level2_part_count;

View File

@ -19,11 +19,6 @@
namespace oceanbase { namespace oceanbase {
namespace storage { namespace storage {
constexpr int64_t next_pow2(const int64_t x)
{
return x ? (1ULL << (8 * sizeof(int64_t) - __builtin_clzll(x - 1))) : 1;
}
template <typename Key, typename Handle> template <typename Key, typename Handle>
class ObHandleCacheNode : public common::ObDLinkBase<ObHandleCacheNode<Key, Handle>> { class ObHandleCacheNode : public common::ObDLinkBase<ObHandleCacheNode<Key, Handle>> {
public: public:
@ -125,7 +120,7 @@ public:
} }
private: private:
static const uint64_t BUCKET_SIZE = next_pow2(N * 2); static const uint64_t BUCKET_SIZE = common::next_pow2(N * 2);
static const uint64_t MASK = BUCKET_SIZE - 1; static const uint64_t MASK = BUCKET_SIZE - 1;
CacheNode nodes_[N]; CacheNode nodes_[N];
int16_t buckets_[BUCKET_SIZE]; int16_t buckets_[BUCKET_SIZE];