clang: do not issue bogus warnings about integer manipulation in hash functions with fsanitize=undefined/integer (#2965)

With -fsanitize=integer every over/under-flowing integer manipulation triggers a warning.
This is extremely useful as it allows to find some non-obvious bugs such as

    for(size_t i = 0; i < N - 1; i++) { ... }

But it comes with a lot of false positives, for instance with every hash function
doing shifting on unsigned integer. Random number generators are also often detected
with this sanitizer.

This marks a few of these functions as safe in this case.

Co-authored-by: Martin Hořeňovský <martin.horenovsky@gmail.com>
This commit is contained in:
Jean-Michaël Celerier 2025-07-02 07:30:36 -04:00 committed by GitHub
parent ceed26842b
commit d134b0cae3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -7,6 +7,12 @@
// SPDX-License-Identifier: BSL-1.0 // SPDX-License-Identifier: BSL-1.0
#include <catch2/internal/catch_random_number_generator.hpp> #include <catch2/internal/catch_random_number_generator.hpp>
#if defined( __clang__ )
# define CATCH2_CLANG_NO_SANITIZE_INTEGER \
__attribute__( ( no_sanitize( "unsigned-integer-overflow" ) ) )
#else
# define CATCH2_CLANG_NO_SANITIZE_INTEGER
#endif
namespace Catch { namespace Catch {
namespace { namespace {
@ -16,6 +22,7 @@ namespace {
#pragma warning(disable:4146) // we negate uint32 during the rotate #pragma warning(disable:4146) // we negate uint32 during the rotate
#endif #endif
// Safe rotr implementation thanks to John Regehr // Safe rotr implementation thanks to John Regehr
CATCH2_CLANG_NO_SANITIZE_INTEGER
uint32_t rotate_right(uint32_t val, uint32_t count) { uint32_t rotate_right(uint32_t val, uint32_t count) {
const uint32_t mask = 31; const uint32_t mask = 31;
count &= mask; count &= mask;
@ -49,6 +56,7 @@ namespace {
} }
} }
CATCH2_CLANG_NO_SANITIZE_INTEGER
SimplePcg32::result_type SimplePcg32::operator()() { SimplePcg32::result_type SimplePcg32::operator()() {
// prepare the output value // prepare the output value
const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u); const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);