Skip to content

fix: make the wrapped successor explicit in CRangesSet under -fsanitize=integer - #7590

Merged
PastaPastaPasta merged 1 commit into
dashpay:developfrom
PastaPastaPasta:fix/rangesset-sanitizer
Aug 13, 2026
Merged

fix: make the wrapped successor explicit in CRangesSet under -fsanitize=integer#7590
PastaPastaPasta merged 1 commit into
dashpay:developfrom
PastaPastaPasta:fix/rangesset-sanitizer

Conversation

@PastaPastaPasta

@PastaPastaPasta PastaPastaPasta commented Aug 12, 2026

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

develop's linux64_asan job is red since #7587 merged. The boundary tests merged there exercise Add(UINT64_MAX), whose half-open end value + 1 intentionally wraps to 0 — the representation the rest of #7587 teaches the class to understand. The asan job builds with -fsanitize=integer, which reports the intentional wrap as unsigned integer overflow: 18446744073709551615 + 1 at util/ranges_set.cpp:27 and fails make check. My verification of #7587 ran the full unit suite but not under sanitizers, which is exactly the gap this slipped through; apologies for the breakage.

What was done?

Spelled the successor as an explicit branch — a file-local WrappedSuccessor(value) (value == UINT64_MAX ? 0 : value + 1) — at the three arithmetic sites in Add()/Remove(). This states the wrap as intent instead of overflow, which is preferable to a sanitizer suppression here: unlike the quorum-snapshot skip-list encoding (suppressed by symbol in eacd9e0 because its wraparound is consensus wire format), this is a private in-memory representation that can simply be written unambiguously.

No behavior change: for every value != UINT64_MAX the expression is value + 1 as before, and for UINT64_MAX it produces the same 0 the wrap produced.

How Has This Been Tested?

Built with --with-sanitizers=undefined,integer (the failing job's relevant checks): util_tests/test_CRanges reproduces the exact CI failure without the fix and passes with it, using the repo's ubsan suppressions file. Full unit suite green on a regular --enable-werror build, rebased on current develop (the linux64_nowallet failure visible on this branch's earlier CI was the pre-existing ScopedBLSLegacyScheme gcc-14 warning, fixed independently by #7586).

Breaking Changes

None.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

CRangesSet now handles the successor of UINT64_MAX as zero during range creation, merging, and splitting. ScopedBLSLegacyScheme now has a capture-only constructor and a separate constructor that requires an explicit boolean to enter a scheme.

Estimated code review effort: 2 (Simple) | ~10 minutes

Mergeability Score: ⚪ Minimal · up to 50b39

The PR makes sanitizer-safe successor handling without changing range behavior. The only current-head issue is a stale adjacent comment for UINT64_MAX's wrapped representation; it has no runtime or user impact, so the PR is merge-ready after normal checks with no actionable merge-blocking risk remaining.

Possibly related PRs

Suggested reviewers: udjinm6

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the primary change: making the wrapped successor explicit in CRangesSet to prevent sanitizer-reported overflow.
Description check ✅ Passed The description directly explains the sanitizer failure, the CRangesSet fix, testing performed, and lack of behavior or breaking changes.
✨ Finishing Touches 💡 1
⚔️ Resolve merge conflicts 💡
  • Resolve merge conflict in branch fix/rangesset-sanitizer
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@thepastaclaw

thepastaclaw commented Aug 12, 2026

Copy link
Copy Markdown

✅ Final review complete — no blockers (commit 8b200cd)

@PastaPastaPasta PastaPastaPasta changed the title fix: make the wrapped successor explicit in CRangesSet under -fsanitize=integer fix: unbreak develop CI (CRangesSet integer-sanitizer wrap, kernel-lib maybe-uninitialized) Aug 12, 2026
@github-actions

Copy link
Copy Markdown

This pull request has conflicts, please rebase.

…ze=integer

The boundary tests merged in dashpay#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 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 50b398d148

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/validation.cpp Outdated
public:
explicit ScopedBLSLegacyScheme(std::optional<bool> enter = std::nullopt) noexcept :
//! Capture the current scheme without changing it.
ScopedBLSLegacyScheme() noexcept : m_saved(bls::bls_legacy_scheme.load()) {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Split the unrelated BLS constructor change

When this commit is reviewed, reverted, or cherry-picked as the advertised CRangesSet sanitizer fix, this independent refactor of ScopedBLSLegacyScheme is silently included even though the commit message describes only the ranges change. That hides a validation-path change from reviewers and prevents the two fixes from being managed independently; move the constructor-overload change into its own commit with its own rationale and validation.

AGENTS.md reference: AGENTS.md:L13-L14

Useful? React with 👍 / 👎.

@PastaPastaPasta
PastaPastaPasta force-pushed the fix/rangesset-sanitizer branch from 50b398d to 8b200cd Compare August 12, 2026 22:05
@PastaPastaPasta PastaPastaPasta changed the title fix: unbreak develop CI (CRangesSet integer-sanitizer wrap, kernel-lib maybe-uninitialized) fix: make the wrapped successor explicit in CRangesSet under -fsanitize=integer Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/util/ranges_set.cpp`:
- Line 37: Update the comment adjacent to Range new_range in Add() to describe
the endpoint using WrappedSuccessor(value), including the UINT64_MAX case where
the representation wraps to 0 instead of always claiming [value, value + 1).
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9847e4f6-4960-4388-b43f-1b50c69ef320

📥 Commits

Reviewing files that changed from the base of the PR and between 583a330 and 50b398d.

📒 Files selected for processing (2)
  • src/util/ranges_set.cpp
  • src/validation.cpp

Comment thread src/util/ranges_set.cpp
// - 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)};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Update the adjacent Add() range comment.

At Line 37, Range new_range uses WrappedSuccessor(value), but the comment still describes [value, value + 1) unconditionally. For UINT64_MAX, the stored representation is {UINT64_MAX, 0}. Reference WrappedSuccessor(value) or document this wrap explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/util/ranges_set.cpp` at line 37, Update the comment adjacent to Range
new_range in Add() to describe the endpoint using WrappedSuccessor(value),
including the UINT64_MAX case where the representation wraps to 0 instead of
always claiming [value, value + 1).

@thepastaclaw thepastaclaw left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final validation — Codex/Sol only (Phase 2 disabled)

The explicit successor helper preserves the existing wrapped range representation while avoiding sanitizer-reported unsigned overflow at all three affected arithmetic sites. One in-scope nitpick remains: Add()'s algorithm comments still describe value + 1 unconditionally instead of the wrapped endpoint used for UINT64_MAX.
Source: reviewer backend model gpt-5.6-sol; final verifier backend model gpt-5.6-sol. openclaw-agent/cliproxy/gpt-5.6-sol is orchestration-only and not reviewer evidence.

Validated zero-blocker Codex/Sol precheck evidence was promoted to final because Phase 2 (Sonnet/Opus) is temporarily disabled. This is Codex/Sol-only final validation, not Codex + Sonnet/Opus coverage.

Review provenance

  • Codex reviewers: gpt-5.6-sol — general (completed)
  • Verifier: gpt-5.6-sol — verifier
  • Sonnet/Opus: not run (Phase 2 disabled — temporary Codex/Sol-only final)
  • Secondary pass: disabled (temporary_phase2_sonnet_disable)

💬 1 nitpick(s)

🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.

In `src/util/ranges_set.cpp`:
- [NITPICK] src/util/ranges_set.cpp:31-36: Describe the wrapped successor in Add() comments
  The implementation now deliberately uses `WrappedSuccessor(value)`, but the adjacent algorithm comments still describe every endpoint as `value + 1`. For `UINT64_MAX`, the stored endpoint is actually `0`, so these comments obscure the boundary behavior this PR makes explicit. Use the helper's name in the range descriptions and document its wrapped endpoint.

Comment thread src/util/ranges_set.cpp
Comment on lines 34 to 36
// 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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💬 Nitpick: Describe the wrapped successor in Add() comments

The implementation now deliberately uses WrappedSuccessor(value), but the adjacent algorithm comments still describe every endpoint as value + 1. For UINT64_MAX, the stored endpoint is actually 0, so these comments obscure the boundary behavior this PR makes explicit. Use the helper's name in the range descriptions and document its wrapped endpoint.

Suggested change
// 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)
// If element is not in CRangesSet, add the encoded range
// [value, WrappedSuccessor(value)); UINT64_MAX uses a wrapped end of 0.
// This operation can cause two merges (three cases):
// - if ranges [x, value) and [WrappedSuccessor(value), y) exist,
// merge all three ranges into [x, y)
// - if [x, value) exists, extend it through value
// - if [WrappedSuccessor(value), y) exists, prepend value to it

source: ['coderabbit']

@PastaPastaPasta
PastaPastaPasta merged commit 981a25d into dashpay:develop Aug 13, 2026
46 of 47 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants