Repository navigation
Fix frame parsing when the ring buffer wraps around - #37
Open
Shumon Fujita (shumon84) wants to merge 1 commit into
Open
Shumon Fujita (shumon84) wants to merge 1 commit into
Shumon Fujita (shumon84) wants to merge 1 commit into
Conversation
- slices_endx dropped the first slice when the end index fell into the second one, so a body spanning the end of the buffer lost its head. The CRC check then failed and the frame was reported as InvalidCrc junk. - find_stx only looked for an STX spanning the two slices when the first slice had an odd length, so it missed the STX otherwise and the frame was skipped as InvalidStx junk. Add a test that shifts the write position of the buffer by one byte at a time so that the frame wraps around at every possible position. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Problem
Parserdrops valid frames whenever a frame wraps around the end of its ring buffer (VecDeque/heapless::Deque), becauseBuffer::data()then returns the bytes as two slices and two helpers mishandle that case:slices_endxdrops the first slice. When the end index falls into the second slice it returns(&[], &b[..endx - a.len()])instead of(a, &b[..endx - a.len()]). A body that spans the end of the buffer loses its head, so the CRC check fails and the frame is reported asInvalidCrcjunk. (get_bodyuses the same helper, so the body would also be truncated.)find_stxonly checks a spanning STX when the first slice has an odd length (buf_a.len() & 1 == 1). WhenEBis the last byte of the first slice and90is the first byte of the second, the STX is missed for even lengths and the frame is skipped asInvalidStxjunk.The existing tests never wrap the buffer (each starts writing at index 0), so neither case was covered.
Impact
kble-eb90 decode(kble v0.4.2, 2048-byte buffer) loses about 1 in 5 frames from a C2A PCDU that sends 431-byte EB90 frames: every frame that wraps around the buffer is dropped asInvalidCrc. A larger--buffer-size(the kble v0.5.0 default) makes the buffer wrap less often, but frames are still lost each time it does.Fix
slices_endx: return(a, &b[..endx - a.len()]).find_stx: check the spanning STX regardless of the first slice's length.Test
test_wraparoundshifts the buffer's write position one byte at a time, so the frame wraps at every possible position. It also puts 0 to 4 junk bytes before the STX, so that an STX spanning the two slices occurs with both odd and even first-slice lengths.lead=0 offset=9(slices_endx).slices_endxfix: fails atlead=1 offset=14(find_stx).I also replayed a 30-second capture of the PCDU's serial output, split into the same chunks
kble-serialportsent over WebSocket, throughDecoder. With a 2048-byte buffer, 0.1.1 decodes 26 of 30 frames; this branch decodes 30 of 30. All 30 frames in the capture have valid CRCs.Note on CI
The Rust workflow fails on
mainregardless of this change: with the pinned toolchain 1.70.0, cargo cannot resolve the current dependencies (getrandom v0.4.3viaproptestuses edition 2024). #34 (Rust 1.99.1) passes CI, so this PR should go green once #34 is merged. I ran the tests,cargo fmt --checkand clippy locally with stable. Clippy's only remaining warning (mismatched_lifetime_syntaxesonParser::read) is in existing code and is not touched here.🤖 Generated with Claude Code