-
Notifications
You must be signed in to change notification settings - Fork 75
fix: handle random length bytes before version bytes #656
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
49ffe1f
37d7cf1
46bceb2
2576f49
3cff6c4
ee8f6ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -341,9 +341,32 @@ class PrefixedStruct(Struct): | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _parse(self, stream, context, path): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subcon1 = Peek(Optional(Bytes(3))) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| peek_version = subcon1.parse_stream(stream, **context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if peek_version not in (b"1.0", b"A01", b"B01", b"L01"): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subcon2 = Bytes(4) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| subcon2.parse_stream(stream, **context) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| valid_versions = (b"1.0", b"A01", b"B01", b"L01") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if peek_version not in valid_versions: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Current stream position does not start with a valid version. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Scan forward to find one. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| current_pos = stream_tell(stream, path) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Read remaining data to find a valid header | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = stream.read() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start_index = -1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Find the earliest occurrence of any valid version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| candidates = [idx for v in valid_versions if (idx := data.find(v)) != -1] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if candidates: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| start_index = min(candidates) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if start_index != -1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Found a valid version header at `start_index`. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Seek to that position (original_pos + index). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+350
to
+362
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Read remaining data to find a valid header | |
| data = stream.read() | |
| start_index = -1 | |
| # Find the earliest occurrence of any valid version | |
| candidates = [idx for v in valid_versions if (idx := data.find(v)) != -1] | |
| if candidates: | |
| start_index = min(candidates) | |
| if start_index != -1: | |
| # Found a valid version header at `start_index`. | |
| # Seek to that position (original_pos + index). | |
| # Read remaining data in chunks to find a valid header | |
| CHUNK_SIZE = 4096 | |
| buffer = b"" | |
| start_index = -1 | |
| found = False | |
| while True: | |
| chunk = stream.read(CHUNK_SIZE) | |
| if not chunk: | |
| break | |
| buffer += chunk | |
| # Check for any valid version header in the buffer | |
| candidates = [idx for v in valid_versions if (idx := buffer.find(v)) != -1] | |
| if candidates: | |
| start_index = min(candidates) | |
| found = True | |
| break | |
| if found and start_index != -1: |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,89 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from roborock.protocol import create_local_decoder, create_local_encoder | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We currently have the pattern that each test module corresponds to an actual model. I know AI likes to make up random test files depending on the subject, but i'd rather see this correspond to a module. Should this be in |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from roborock.roborock_message import RoborockMessage, RoborockMessageProtocol | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TEST_LOCAL_KEY = "local_key" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_decoder_clean_message(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoder = create_local_encoder(TEST_LOCAL_KEY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoder = create_local_decoder(TEST_LOCAL_KEY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg = RoborockMessage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protocol=RoborockMessageProtocol.RPC_REQUEST, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| payload=b"test_payload", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version=b"1.0", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| seq=1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| random=123, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoded = encoder(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoded = decoder(encoded) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(decoded) == 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert decoded[0].payload == b"test_payload" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+7
to
+22
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe you can write the first three tests as one test like this:
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_decoder_4byte_padding(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Test existing behavior: 4 byte padding should be skipped.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoder = create_local_encoder(TEST_LOCAL_KEY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoder = create_local_decoder(TEST_LOCAL_KEY) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg = RoborockMessage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protocol=RoborockMessageProtocol.RPC_REQUEST, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| payload=b"test_payload", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version=b"1.0", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoded = encoder(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Prepend 4 bytes of garbage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| garbage = b"\x00\x00\x05\xa1" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = garbage + encoded | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoded = decoder(data) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(decoded) == 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert decoded[0].payload == b"test_payload" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_decoder_variable_padding(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Test proposed fix: variable length padding should be skipped.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Lash-L marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoder = create_local_encoder(TEST_LOCAL_KEY, connect_nonce=123, ack_nonce=456) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoder = create_local_decoder(TEST_LOCAL_KEY, connect_nonce=123, ack_nonce=456) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg = RoborockMessage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protocol=RoborockMessageProtocol.RPC_REQUEST, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| payload=b"test_payload", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version=b"L01", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoded = encoder(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Prepend 6 bytes of garbage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| garbage = b"\x00\x00\x05\xa1\xff\xff" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| data = garbage + encoded | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoded = decoder(data) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(decoded) == 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert decoded[0].payload == b"test_payload" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_decoder_split_padding_variable(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Test variable padding split across chunks.""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoder = create_local_encoder(TEST_LOCAL_KEY, connect_nonce=123, ack_nonce=456) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoder = create_local_decoder(TEST_LOCAL_KEY, connect_nonce=123, ack_nonce=456) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg = RoborockMessage( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| protocol=RoborockMessageProtocol.RPC_REQUEST, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| payload=b"test_payload", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version=b"L01", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| encoded = encoder(msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| garbage = b"\x00\x00\x05\xa1\xff\xff" # 6 bytes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Send garbage | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoded1 = decoder(garbage) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(decoded1) == 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Send message | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| decoded2 = decoder(encoded) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert len(decoded2) == 1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert decoded2[0].payload == b"test_payload" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.