From 08d222fe084c5e3f5e65013e0e976f29fc5d2c4f Mon Sep 17 00:00:00 2001 From: Niklas Uhl Date: Thu, 4 Dec 2025 16:21:02 +0100 Subject: [PATCH 1/3] Avoid UB in MSB computation in feistel permutation. 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. --- kagen/tools/random_permutation.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kagen/tools/random_permutation.h b/kagen/tools/random_permutation.h index dead687..1c3faa2 100644 --- a/kagen/tools/random_permutation.h +++ b/kagen/tools/random_permutation.h @@ -84,6 +84,11 @@ std::uint8_t most_significant_bit_set(const Data arg) { constexpr std::size_t arg_width = std::numeric_limits::digits; auto log2 = static_cast(arg_width); + // __builtin_clz(l) is undefined for 0 + if (arg == 0) { + return 0; + } + if constexpr (arg_width == std::numeric_limits::digits) { log2 -= __builtin_clz(arg); } else { From ec7c0af481afb65eef614857a9244fa64d09ae9b Mon Sep 17 00:00:00 2001 From: Niklas Uhl Date: Thu, 4 Dec 2025 17:14:12 +0100 Subject: [PATCH 2/3] Make msb function less easy to misuse. --- kagen/tools/random_permutation.h | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/kagen/tools/random_permutation.h b/kagen/tools/random_permutation.h index 1c3faa2..d4e44dc 100644 --- a/kagen/tools/random_permutation.h +++ b/kagen/tools/random_permutation.h @@ -79,24 +79,31 @@ inline uint8_t most_significant_bit_set(Data bytes) { asm("bsr %1,%0" : "=r"(msb) : "r"(bytes)); return asserting_cast(msb); }*/ -template +template < + typename Data, typename Enable = std::enable_if_t< + std::is_same_v || std::is_same_v + || std::is_same_v>> std::uint8_t most_significant_bit_set(const Data arg) { - constexpr std::size_t arg_width = std::numeric_limits::digits; - auto log2 = static_cast(arg_width); + constexpr std::size_t width = std::numeric_limits::digits; + - // __builtin_clz(l) is undefined for 0 + // __builtin_clz* is undefined for 0 if (arg == 0) { return 0; } - if constexpr (arg_width == std::numeric_limits::digits) { - log2 -= __builtin_clz(arg); - } else { - static_assert(arg_width == std::numeric_limits::digits, "unsupported data type width"); + std::size_t leading_zeros = 0; + + if constexpr (std::is_same_v) { + leading_zeros = __builtin_clz(arg); + } else if constexpr (std::is_same_v) { log2 -= __builtin_clzl(arg); + leading_zeros = __builtin_clzl(arg); + } else { + static_assert(std::is_same_v); + leading_zeros = __builtin_clzll(arg); } - - return log2 - 1; + return asserting_cast(width - leading_zeros - 1); } #define UNUSED(expr) (void)(expr) From f0a08821c082ae7601fce43595b16cfc4ea6e2e0 Mon Sep 17 00:00:00 2001 From: Niklas Uhl Date: Thu, 4 Dec 2025 17:17:08 +0100 Subject: [PATCH 3/3] fixup! Make msb function less easy to misuse. --- kagen/tools/random_permutation.h | 1 - 1 file changed, 1 deletion(-) diff --git a/kagen/tools/random_permutation.h b/kagen/tools/random_permutation.h index d4e44dc..c4ea223 100644 --- a/kagen/tools/random_permutation.h +++ b/kagen/tools/random_permutation.h @@ -97,7 +97,6 @@ std::uint8_t most_significant_bit_set(const Data arg) { if constexpr (std::is_same_v) { leading_zeros = __builtin_clz(arg); } else if constexpr (std::is_same_v) { - log2 -= __builtin_clzl(arg); leading_zeros = __builtin_clzl(arg); } else { static_assert(std::is_same_v);