Fix fill() corrupting data when the fill pattern is longer than one word#58
Open
gaoflow wants to merge 1 commit into
Open
Fix fill() corrupting data when the fill pattern is longer than one word#58gaoflow wants to merge 1 commit into
gaoflow wants to merge 1 commit into
Conversation
fill() built each gap-filling Segment's data as `value * fill_size_words`, i.e. `fill_size_words * len(value)` bytes. That equals the gap only when `len(value) == word_size_bytes`; a longer fill pattern produced too many bytes, overran the gap and silently overwrote the following segment, destroying existing data. Repeat the pattern and clamp it to exactly the gap size, which is byte-identical to the previous behaviour for the normal one-word pattern. Fixes eerimoq#51.
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.
Fixes #51.
The bug
fill()silently corrupts (or destroys) existing segment data when the fill pattern is longer than one word:A smaller case mangles rather than deletes: filling a 1-byte gap between
cafeandbabewithb" -"yieldsb'cafe -bab'(and the segment view,b'cafe -babe', is even a different length thanas_binary()). The docstring says fill "Fill empty space between segments", so altering bytes that already hold data is wrong under any fill semantics.Root cause
bincopy.py, infill():The
Segmentis declared to spanfill_sizebytes, but its datavalue * fill_size_wordshasfill_size_words * len(value)bytes. These are equal only whenlen(value) == word_size_bytes. For a longervaluethe oversized data overruns the gap, and_segments.add()overwrites the following segment.The fix
Repeat
valueand clamp it to exactly the gap size:This is byte-identical to the current behaviour for the normal
len(value) == word_size_bytescase (including the defaultb'\xff' * word_size_bytes), so existing fills are unchanged — it only stops the overrun. This matches the repeat-the-pattern semantics suggested in #51; I went with clamp-to-gap rather than raising, since it is the backward-compatible choice and the default fill keeps working. Happy to switch to raising on a non-dividing pattern if you'd prefer that.Tests
test_fill_pattern_longer_than_wordcovers: a multi-byte pattern over a 2-byte gap (trailing segment preserved), a 2-byte pattern over a 1-byte gap, the default-value path (unchanged),word_size_bits=16with a two-word pattern, and anas_binary()/segment length-consistency assert. The first case fails onmaster(b'AAAAxyzxyz' != b'AAAAxyBBBB') and passes with the fix; the full suite stays green (103 passed).