Run the maxVersion "borrowed range version" check (#95) #106

Open
weaselbot wants to merge 1 commits from weaselbot/conflict-set:weaselbot/issue-95 into main
pull from: weaselbot/conflict-set:weaselbot/issue-95
Member

Closes #95.

checkMaxVersion() derived its lookup key from getSearchPath(root). root is the tree root, whose search path is always the empty string, and strinc("") fails, so the block accounting for the range version of the first key after the node's subtree never executed — for any node, on any input, since 9363d78 introduced it.

Changes

  1. checkMaxVersion() now derives the key from getSearchPath(node). root is left doing only what it was meant to do: being the base of the firstGeq search.
  2. firstGeqLogical() — whose only caller is that block — dereferenced a null sibling when the search key sorts after every key in the tree (nextSibling() can return nullptr). It now returns nullptr in that case, matching firstGeqPhysical().

Verification

  • ./build/fuzz_driver corpus/003fdafe6e5f359e1043927b266e6ed6193562bc SEGVs with only change (1) applied, and passes with both.
  • All 2845 corpus/ inputs pass with the fix, and the borrowed-range term is now actually reached: instrumenting the block counts ~1.4M ok hits and ~1.4M non-null firstGeq results over the corpus (0 before the fix).
  • Full ctest suite passes (8601/8601) in a Debug clang build; the corpus also passes in the -DUSE_64_BIT=1, -DUSE_SIMD_FALLBACK=ON and gcc configurations (the CI matrix).
  • firstGeqLogical() was cross-checked against a brute-force "first key >= q" over 500 random trees (all keys, prefixes, appended/incremented variants and random keys including \x00/\xff), with no mismatches.

No test is added: corpus/003fdafe6e5f359e1043927b266e6ed6193562bc (already run by conflict_set_fuzz_* in ctest) is the crash reproduction, and every corpus input now exercises the previously dead check.

Closes #95. `checkMaxVersion()` derived its lookup key from `getSearchPath(root)`. `root` is the tree root, whose search path is always the empty string, and `strinc("")` fails, so the block accounting for the range version of the first key *after* the node's subtree never executed — for any node, on any input, since 9363d78 introduced it. **Changes** 1. `checkMaxVersion()` now derives the key from `getSearchPath(node)`. `root` is left doing only what it was meant to do: being the base of the `firstGeq` search. 2. `firstGeqLogical()` — whose only caller is that block — dereferenced a null sibling when the search key sorts after every key in the tree (`nextSibling()` can return `nullptr`). It now returns `nullptr` in that case, matching `firstGeqPhysical()`. **Verification** * `./build/fuzz_driver corpus/003fdafe6e5f359e1043927b266e6ed6193562bc` SEGVs with only change (1) applied, and passes with both. * All 2845 `corpus/` inputs pass with the fix, and the borrowed-range term is now actually reached: instrumenting the block counts ~1.4M `ok` hits and ~1.4M non-null `firstGeq` results over the corpus (0 before the fix). * Full `ctest` suite passes (8601/8601) in a Debug clang build; the corpus also passes in the `-DUSE_64_BIT=1`, `-DUSE_SIMD_FALLBACK=ON` and gcc configurations (the CI matrix). * `firstGeqLogical()` was cross-checked against a brute-force "first key >= q" over 500 random trees (all keys, prefixes, appended/incremented variants and random keys including `\x00`/`\xff`), with no mismatches. No test is added: `corpus/003fdafe6e5f359e1043927b266e6ed6193562bc` (already run by `conflict_set_fuzz_*` in ctest) is the crash reproduction, and every corpus input now exercises the previously dead check.
weaselbot added 1 commit 2026-11-10 21:05:56 +00:00
Run the maxVersion "borrowed range version" check
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 4m17s
CI / release (arm64, , ubuntu-latest-arm64) (pull_request) Successful in 3m31s
CI / pre-commit (pull_request) Successful in 2m44s
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 4m21s
CI / test (amd64, -DCMAKE_CXX_FLAGS=-DUSE_64_BIT=1, 21, , 64-bit-versions, ubuntu-latest-amd64) (pull_request) Successful in 3m34s
CI / test (amd64, -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++, 21, , gcc, ubuntu-latest-amd64) (pull_request) Successful in 3m30s
CI / test (amd64, -DUSE_SIMD_FALLBACK=ON, 21, , simd-fallback, ubuntu-latest-amd64) (pull_request) Successful in 3m34s
CI / release (amd64, -DMSAN_TOOLCHAIN_PATH=/opt/msan, ubuntu-latest-amd64) (pull_request) Successful in 5m58s
CI / coverage (pull_request) Successful in 3m59s
3d997d5c57
checkMaxVersion derived the key to look up from getSearchPath(root), but
`root` is the tree root, which is always the empty string. strinc("")
fails, so the block accounting for the range version of the first key
after the node's subtree never ran, for any node of any input, since it
was introduced in 9363d78. Use the node's own search path so the block
runs (and so `root` is left doing only what it was meant to do: being the
base of the search).

firstGeqLogical(), whose only caller is that block, dereferenced a null
sibling when the search key sorts after every key in the tree. It now
returns nullptr there, matching firstGeqPhysical().

Closes #95
All checks were successful
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 4m17s
Required
Details
CI / release (arm64, , ubuntu-latest-arm64) (pull_request) Successful in 3m31s
Required
Details
CI / pre-commit (pull_request) Successful in 2m44s
Required
Details
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 4m21s
Required
Details
CI / test (amd64, -DCMAKE_CXX_FLAGS=-DUSE_64_BIT=1, 21, , 64-bit-versions, ubuntu-latest-amd64) (pull_request) Successful in 3m34s
Required
Details
CI / test (amd64, -DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++, 21, , gcc, ubuntu-latest-amd64) (pull_request) Successful in 3m30s
Required
Details
CI / test (amd64, -DUSE_SIMD_FALLBACK=ON, 21, , simd-fallback, ubuntu-latest-amd64) (pull_request) Successful in 3m34s
Required
Details
CI / release (amd64, -DMSAN_TOOLCHAIN_PATH=/opt/msan, ubuntu-latest-amd64) (pull_request) Successful in 5m58s
Required
Details
CI / coverage (pull_request) Successful in 3m59s
Required
Details
You are not authorized to merge this pull request.
This pull request can be merged automatically.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u https://git.weaselab.dev/weaselbot/conflict-set weaselbot/issue-95:weaselbot-weaselbot/issue-95
git checkout weaselbot-weaselbot/issue-95
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#106