From 8b200cd05adab8cda9b085fe249faebff06bd8ca Mon Sep 17 00:00:00 2001 From: pasta Date: Wed, 12 Aug 2026 16:30:08 -0500 Subject: [PATCH] fix: make the wrapped successor explicit in CRangesSet under -fsanitize=integer The boundary tests merged in #7587 exercise Add(UINT64_MAX), whose value + 1 half-open end intentionally wraps to 0. The linux64_asan job runs with -fsanitize=integer, which reports the wrap as unsigned integer overflow at util/ranges_set.cpp:27 and fails make check on develop. Spell the successor as an explicit branch (WrappedSuccessor) at the three arithmetic sites so the wrap is stated intent instead of overflow. No behavior change: the guarded value compares and inserts exactly as the wrapped arithmetic did. Verified with a --with-sanitizers=undefined,integer build: util_tests/test_CRanges reproduces the CI failure unfixed and passes fixed. Co-Authored-By: Claude Fable 5 --- src/util/ranges_set.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/util/ranges_set.cpp b/src/util/ranges_set.cpp index 9e55dbfd8448..556df3581d9b 100644 --- a/src/util/ranges_set.cpp +++ b/src/util/ranges_set.cpp @@ -6,6 +6,16 @@ #include +namespace { +//! Successor of a value in the half-open range encoding: the range containing +//! UINT64_MAX stores a wrapped end of 0. Spelled as a branch so the wrap is +//! explicit intent rather than arithmetic overflow (-fsanitize=integer). +constexpr uint64_t WrappedSuccessor(uint64_t value) noexcept +{ + return value == std::numeric_limits::max() ? 0 : value + 1; +} +} // namespace + CRangesSet::Range::Range() : CRangesSet::Range::Range(0, 0) {} CRangesSet::Range::Range(uint64_t begin_in, uint64_t end_in) : @@ -24,7 +34,7 @@ bool CRangesSet::Add(uint64_t value) // all 3 of them should be merged in one range [x, y) // - if there's exist a range [x, value) - we need to replace it to new range [x, value + 1) // - if there's exist a range [value + 1, y) - we need to replace it to new range [value, y) - Range new_range{value, value + 1}; + Range new_range{value, WrappedSuccessor(value)}; auto it = ranges.lower_bound({value, value}); if (it != ranges.begin()) { auto prev = it; @@ -37,7 +47,7 @@ bool CRangesSet::Add(uint64_t value) } const auto next = it; if (next != ranges.end()) { - if (next->begin == value + 1) { + if (next->begin == WrappedSuccessor(value)) { new_range.end = next->end; ranges.erase(next); } @@ -67,8 +77,8 @@ bool CRangesSet::Remove(uint64_t value) const auto ret = ranges.insert({current_range.begin, value}); assert(ret.second); } - if (value + 1 != current_range.end) { - const auto ret = ranges.insert({value + 1, current_range.end}); + if (WrappedSuccessor(value) != current_range.end) { + const auto ret = ranges.insert({WrappedSuccessor(value), current_range.end}); assert(ret.second); } return true;