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
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.
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.
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 / 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
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
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
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.
Closes #95.
checkMaxVersion()derived its lookup key fromgetSearchPath(root).rootis the tree root, whose search path is always the empty string, andstrinc("")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, since9363d78introduced it.Changes
checkMaxVersion()now derives the key fromgetSearchPath(node).rootis left doing only what it was meant to do: being the base of thefirstGeqsearch.firstGeqLogical()— whose only caller is that block — dereferenced a null sibling when the search key sorts after every key in the tree (nextSibling()can returnnullptr). It now returnsnullptrin that case, matchingfirstGeqPhysical().Verification
./build/fuzz_driver corpus/003fdafe6e5f359e1043927b266e6ed6193562bcSEGVs with only change (1) applied, and passes with both.corpus/inputs pass with the fix, and the borrowed-range term is now actually reached: instrumenting the block counts ~1.4Mokhits and ~1.4M non-nullfirstGeqresults over the corpus (0 before the fix).ctestsuite passes (8601/8601) in a Debug clang build; the corpus also passes in the-DUSE_64_BIT=1,-DUSE_SIMD_FALLBACK=ONand 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 byconflict_set_fuzz_*in ctest) is the crash reproduction, and every corpus input now exercises the previously dead check.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 in9363d78. 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 #95View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.