Reject multiple source keys in BITOP NOT - #2041
Merged
kevin-montrose merged 4 commits intoAug 12, 2026
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR aligns Garnet’s BITOP NOT behavior with Redis by rejecting calls that provide more than one source key, eliminating the current undefined/accidental behavior where extra source keys are silently accepted.
Changes:
- Added argument-count validation so
BITOP NOTerrors when more than one source key is provided. - Introduced a Redis-matching error string constant for the unary
NOTviolation. - Added a regression test covering both the accepted unary form and rejected multi-source forms, and corrected docs to describe unary
NOT.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
libs/server/Resp/Bitmap/BitmapCommands.cs |
Enforces unary semantics for BITOP NOT (parseState.Count > 2 aborts with a specific error). |
libs/server/Resp/CmdStrings.cs |
Adds RESP_ERR_BITOP_NOT_SINGLE_SOURCE_KEY with the Redis-compatible message text. |
test/standalone/Garnet.test.complexstring/GarnetBitmapTests.cs |
Adds regression test ensuring multi-source NOT is rejected and variadic ops remain unaffected. |
website/docs/commands/analytics.md |
Fixes BITOP NOT description to reflect unary behavior. |
hexonal (hexonal)
force-pushed
the
fix-bitop-not-single-source-key
branch
3 times, most recently
from
August 8, 2026 04:50
42a7e6e to
a603585
Compare
BITOP NOT is unary, but Garnet silently accepted extra source keys and produced an undefined result (the destination took the length of the longest source with the remaining bytes left zero) instead of the error Redis returns. NetworkStringBitOperation validated the argument count for the variadic operators and for DIFF, but never enforced that NOT has exactly one source key. Reject NOT with more than one source key, matching Redis' message. Also correct the command doc, which described NOT as operating 'between multiple keys', contradicting its own unary syntax.
hexonal (hexonal)
force-pushed
the
fix-bitop-not-single-source-key
branch
from
August 10, 2026 01:46
a603585 to
ade2c73
Compare
kevin-montrose
approved these changes
Aug 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom
BITOP NOTis a unary operation — it inverts a single source key. Garnet silently accepts more than one source key and produces an undefined result instead of the error Redis returns.Debug build of
GarnetServerat 4ba5ebf:The destination takes the length of the longest source (10), the first two bytes are
NOT("ab"), and the rest are zero — a result that corresponds to no well-defined operation. Redis rejects this outright:Root cause
libs/server/Resp/Bitmap/BitmapCommands.cs,NetworkStringBitOperation. The method validates the argument count for the variadic operators — at least one source key (parseState.Count < 2), the two-source minimum forDIFF, and the 64-key limit — but never enforces thatNOThas exactly one source key. Extra keys are passed through toStringBitOperation, which processes them as ifNOTwere variadic.Garnet already carries the sibling check for
DIFF(RESP_ERR_BITOP_DIFF_TWO_SOURCE_KEYS_REQUIRED); the unary check forNOTwas simply missing.Fix
Add the unary check next to the existing
DIFFcheck.parseStateis[destkey, src1, ...], so a validNOThasCount == 2:with
RESP_ERR_BITOP_NOT_SINGLE_SOURCE_KEY => "ERR BITOP NOT must be called with a single source key."u8(byte-for-byte the Redis message).Count < 2is already rejected as wrong-number-of-arguments above, so this only rejects the extra-source case.AND/OR/XOR/DIFFare untouched.Tests
GarnetBitmapTests.BitmapBitOpNotRejectsMultipleSourceKeys:BITOP NOT dst a(single source) → still works, destination length 2.BITOP NOT dst a bandBITOP NOT dst a b a→ERR BITOP NOT must be called with a single source key.BITOP AND/OR/XOR dst a bstill accept multiple sources (length 10).Fails on unpatched main (the multi-source
NOTis accepted, no exception thrown); passes with the fix. FullGarnetBitmapTests(359) stays green.Docs
website/docs/commands/analytics.mddescribedBITOP NOTas operating "between multiple keys" — a copy-paste artifact from the variadic operators that contradicts its own unary syntax line (BITOP NOT destkey srckey). Corrected to describe the single-source operation this change now enforces.