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.
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
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
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 main2026-08-31 01:14:11 +00:00
andrew
deleted branch weaselbot/issue-822026-08-31 01:14:11 +00:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
One-line typo fix in the
#if DEBUG_VERBOSE && !defined(NDEBUG)debug block at the top of Phase 2 ofweaselab::ConflictSet::Impl::interleavedWrites(ConflictSet.cpp:4984).The loop that resolves the stored
endInsertionPoint'sreleaseDeferred/forwardTochain followed the begin node's chain instead of the end node's:Once
bis fully resolved (b->releaseDeferred == false), itsforwardTofield aliases theEntryunion member (version bytes), soe = b->forwardToassigns garbage and the loop dereferences it — a wild-pointer SEGV (or hang) on anyDEBUG_VERBOSE 1debug 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 ownforwardTo, so this was a typo.Verification
ec1b476(gcc, Debug, aarch64): withDEBUG_VERBOSE 1,./fuzz_driver corpus/003fdafe6e5f359e1043927b266e6ed6193562bcreportsAddressSanitizer: SEGV ... in weaselab::ConflictSet::Impl::interleavedWrites ... ConflictSet.cpp:4983— matching the issue's reproduction.DEBUG_VERBOSE 1, the same input runs cleanly (exit 0) and the "end:" search path prints correctly.DEBUG_VERBOSE 0): fullctestsuite 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