From 3d997d5c575a829829aca6e809cd040859bc7862 Mon Sep 17 00:00:00 2001 From: Weaselbot Date: Tue, 10 Nov 2026 16:05:49 -0500 Subject: [PATCH] Run the maxVersion "borrowed range version" 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 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 --- ConflictSet.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ConflictSet.cpp b/ConflictSet.cpp index 3273dc2..6635463 100644 --- a/ConflictSet.cpp +++ b/ConflictSet.cpp @@ -5631,6 +5631,9 @@ Node *firstGeqLogical(Node *n, const TrivialSpan key) { goto downLeftSpine; } else { n = nextSibling(n); + if (n == nullptr) { + return nullptr; + } goto downLeftSpine; } } @@ -5928,7 +5931,9 @@ checkMaxVersion(Node *root, Node *node, InternalVersionT oldestVersion, expected = std::max(expected, child->entry.rangeVersion); } } - auto key = getSearchPath(root); + // Account for the range version of the first key after `node`'s subtree: a + // range write spanning the subtree is recorded there. + auto key = getSearchPath(node); bool ok; auto inc = strinc(key, ok); if (ok) { -- 2.43.0