Repository navigation
fix(scan): check bitset length in PreviousSet and NextSet, avoid shift-by-64 and signed overflow - #245
Open
mazkev wants to merge 1 commit into
Open
fix(scan): check bitset length in PreviousSet and NextSet, avoid shift-by-64 and signed overflow#245mazkev wants to merge 1 commit into
mazkev wants to merge 1 commit into
Conversation
…t-by-64 and signed overflow
This branch has not been deployed
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.
Summary
This PR addresses boundary inconsistencies across scan/search methods (
PreviousSet,NextSet,NextSetMany), eliminates an undefined shift-by-64 inPreviousSet/PreviousClear, and fixes a signed integer cast inwordsNeededUnbound.Problem Details & Fixes
Logical length bounds check in
PreviousSet,NextSet, andNextSetMany:fix/previous-clear-logical-length),PreviousClearwas updated to checkif i >= b.length { return 0, false }so queries beyond the logical length are cleanly rejected.PreviousSet,NextSet, andNextSetManydid not perform this check.b := New(10).Set(5):b.PreviousSet(20)returned(5, true)because index 20 falls within the first 64-bit backing word.b.PreviousSet(64)returned(0, false)because word 1 was not allocated inb.set.>= b.length). Returning different results based solely on backing slice allocation boundaries is unexpected.if i >= b.length { return 0, false }toPreviousSet,NextSet, andNextSetManyto matchPreviousClear,NextClear, andTest.Shift-by-64 in
PreviousSetandPreviousClear:word & ((1 << (wordsIndex(i) + 1)) - 1). WhenwordsIndex(i) == 63, this evaluated1 << 64on auint64.word & (allBits >> (wordSize - 1 - wordsIndex(i))), avoiding shifting by 64 bits and working portably across compilers and architectures without arithmetic subtraction.Signed integer conversion in
wordsNeededUnbound:wordsNeededUnboundhad(int(i) + wordMask) >> log2WordSize. For large values ofiwhere the high bit was set (e.g.1 << 63), convertingint(i)produced a negative integer, causing negative return values.int((i + wordMask) >> log2WordSize).Tests Added
TestPreviousSetBeyondLength: Verifies thatPreviousSetreturns(0, false)for indices beyond the bitset's logical length.TestNextSetBeyondLength: Verifies thatNextSetreturns(0, false)for indices beyond length.TestNextSetManyBeyondLength: Verifies thatNextSetManyreturns empty results for indices beyond length.TestWordsNeededUnboundSignedCast: Verifies non-negative return values for largeuintinputs.TestPreviousSetWordBoundary: Verifies correct behavior whenwordsIndex(i) == 63.go test ./...andgo vet ./...across amd64 and 386).