Fix broken endInsertionPoint forwarding chain resolution in DEBUG_VERBOSE print #83

Merged
andrew merged 1 commits from weaselbot/conflict-set:weaselbot/issue-82 into main 2026-08-31 01:14:11 +00:00
Member

One-line typo fix in the #if DEBUG_VERBOSE && !defined(NDEBUG) debug block at the top of Phase 2 of weaselab::ConflictSet::Impl::interleavedWrites (ConflictSet.cpp:4984).

The loop that resolves the stored endInsertionPoint's releaseDeferred/forwardTo chain followed the begin node's chain instead of the end node's:

           while (e->releaseDeferred) {
-            e = b->forwardTo;
+            e = e->forwardTo;
           }

Once b is fully resolved (b->releaseDeferred == false), its forwardTo field aliases the Entry union member (version bytes), so e = b->forwardTo assigns garbage and the loop dereferences it — a wild-pointer SEGV (or hang) on any DEBUG_VERBOSE 1 debug build, plus a nonsense printed "end:" search path. The production code resolving the same chains in the loop body and in Phase 3 already used the node's own forwardTo, so this was a typo.

Verification

  • Reproduced the issue on HEAD ec1b476 (gcc, Debug, aarch64): with DEBUG_VERBOSE 1, ./fuzz_driver corpus/003fdafe6e5f359e1043927b266e6ed6193562bc reports AddressSanitizer: SEGV ... in weaselab::ConflictSet::Impl::interleavedWrites ... ConflictSet.cpp:4983 — matching the issue's reproduction.
  • With this fix and DEBUG_VERBOSE 1, the same input runs cleanly (exit 0) and the "end:" search path prints correctly.
  • Stock configuration (DEBUG_VERBOSE 0): full ctest suite passes — 8598/8598 tests passed (all corpus fuzz tests, blackbox/valgrind, script tests, skip list, hash table, C & C++ API tests) — and the built binaries are bit-identical to HEAD (the changed code is compiled out entirely), so this is a no-op for release behavior.

Closes #82

One-line typo fix in the `#if DEBUG_VERBOSE && !defined(NDEBUG)` debug block at the top of Phase 2 of `weaselab::ConflictSet::Impl::interleavedWrites` (ConflictSet.cpp:4984). The loop that resolves the stored `endInsertionPoint`'s `releaseDeferred`/`forwardTo` chain followed the **begin** node's chain instead of the end node's: ```diff while (e->releaseDeferred) { - e = b->forwardTo; + e = e->forwardTo; } ``` Once `b` is fully resolved (`b->releaseDeferred == false`), its `forwardTo` field aliases the `Entry` union member (version bytes), so `e = b->forwardTo` assigns garbage and the loop dereferences it — a wild-pointer SEGV (or hang) on any `DEBUG_VERBOSE 1` debug build, plus a nonsense printed "end:" search path. The production code resolving the same chains in the loop body and in Phase 3 already used the node's own `forwardTo`, so this was a typo. **Verification** - Reproduced the issue on HEAD `ec1b476` (gcc, Debug, aarch64): with `DEBUG_VERBOSE 1`, `./fuzz_driver corpus/003fdafe6e5f359e1043927b266e6ed6193562bc` reports `AddressSanitizer: SEGV ... in weaselab::ConflictSet::Impl::interleavedWrites ... ConflictSet.cpp:4983` — matching the issue's reproduction. - With this fix and `DEBUG_VERBOSE 1`, the same input runs cleanly (exit 0) and the "end:" search path prints correctly. - Stock configuration (`DEBUG_VERBOSE 0`): full `ctest` suite passes — 8598/8598 tests passed (all corpus fuzz tests, blackbox/valgrind, script tests, skip list, hash table, C & C++ API tests) — and the built binaries are bit-identical to HEAD (the changed code is compiled out entirely), so this is a no-op for release behavior. Closes #82
weaselbot added 1 commit 2026-08-31 00:17:40 +00:00
Fix broken endInsertionPoint forwarding chain resolution in DEBUG_VERBOSE print
CI / pre-commit (pull_request) Successful in 2m8s
CI / test (arm64, -DCMAKE_BUILD_TYPE=Debug -DMSAN_TOOLCHAIN_PATH=/opt/msan, 22, https://minio.weaselab.dev/public/aarch64/msan-toolchain-22.1.8.tar.zst, debug-arm64, ubuntu-latest-arm64) (pull_request) Successful in 3m46s
CI / test (amd64, -DCMAKE_BUILD_TYPE=Debug -DMSAN_TOOLCHAIN_PATH=/opt/msan, 21, https://minio.weaselab.dev/public/x86_64/msan-toolchain-21.1.8.tar.zst, debug, ubuntu-latest-amd64) (pull_request) Successful in 4m2s
CI / release (arm64, , ubuntu-latest-arm64) (pull_request) Successful in 3m26s
CI / test (amd64, -DCMAKE_CXX_FLAGS=-DUSE_64_BIT=1, 21, , 64-bit-versions, ubuntu-latest-amd64) (pull_request) Successful in 3m24s
CI / test (amd64, -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++, 21, , gcc, ubuntu-latest-amd64) (pull_request) Successful in 3m16s
CI / test (amd64, -DUSE_SIMD_FALLBACK=ON, 21, , simd-fallback, ubuntu-latest-amd64) (pull_request) Successful in 3m21s
CI / release (amd64, -DMSAN_TOOLCHAIN_PATH=/opt/msan, ubuntu-latest-amd64) (pull_request) Successful in 5m35s
CI / coverage (pull_request) Successful in 3m48s
9a2c64d31c
In the Phase 2 debug block of ConflictSet::Impl::interleavedWrites, the
loop resolving the end insertion point's releaseDeferred/forwardTo chain
followed the begin node's chain instead (e = b->forwardTo). Once b is
resolved, b->forwardTo aliases the Entry union member, so e was assigned
garbage derived from version bytes and the loop dereferenced it,
causing a SEGV or hang whenever DEBUG_VERBOSE builds traced writes.

Use the end node's own forwarding chain (e = e->forwardTo), matching
the production code in the same loop body and in Phase 3.
andrew merged commit 8a16f9a6d6 into main 2026-08-31 01:14:11 +00:00
andrew deleted branch weaselbot/issue-82 2026-08-31 01:14:11 +00:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: weaselab/conflict-set#83