Avoid UB in MSB computation in feistel permutation.#87
Conversation
While this has no impact on the actual implementation, the missing check resulted in a failed assertion https://github.com/KarlsruheGraphGeneration/KaGen/blob/1118666271f36a8c71018768e2de459f0e5ff1c3/kagen/tools/random_permutation.h#L297 When the left half is all zeros, `most_significant_bit_set` is undefined and may return arbitrary large values, making this assertion fail in debug builds.
There was a problem hiding this comment.
AI suggests something like
template <typename Data>
std::uint8_t most_significant_bit_set(const Data arg) {
static_assert(std::is_unsigned<Data>::value, "Data must be an unsigned integral type.");
// __builtin_clz* are undefined for 0
if (arg == 0) {
return 0;
}
constexpr std::size_t width = std::numeric_limits<Data>::digits; // number of value bits
std::size_t leading_zeros = 0;
if constexpr (width == std::numeric_limits<unsigned int>::digits) {
leading_zeros = static_cast<std::size_t>(__builtin_clz(static_cast<unsigned int>(arg)));
} else if constexpr (width == std::numeric_limits<unsigned long>::digits) {
leading_zeros = static_cast<std::size_t>(__builtin_clzl(static_cast<unsigned long>(arg)));
} else if constexpr (width == std::numeric_limits<unsigned long long>::digits) {
leading_zeros = static_cast<std::size_t>(__builtin_clzll(static_cast<unsigned long long>(arg)));
} else {
static_assert(width == std::numeric_limits<unsigned long long>::digits,
"Unsupported Data width for builtin clz");
}
// 0-based index of the most significant set bit
const std::size_t msb_index = width - 1 - leading_zeros;
return static_cast<std::uint8_t>(msb_index);
}
what do you think?
Do we ever call it with signed integers? If not, we could just a std::is_same_v<unsigned ..., Data>?
|
It's only ever called with |
|
Since the code uses |
|
There might still be happening weird things when the number of vertices to permute is zero, we should rename |
While this has no impact on the actual implementation, the missing
check resulted in a failed assertion
KaGen/kagen/tools/random_permutation.h
Line 297 in 1118666
When the left half is all zeros,
most_significant_bit_setisundefined and may return arbitrary large values, making this assertion
fail in debug builds.