Skip to content

Commit 47ae8d2

Browse files
Add bounds check for file content in FilesResponse.decode_body
The file content slice used Python's silent truncation behavior when the declared size exceeded available data. Now raises DecodeError with a clear message about the truncation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 6d21721 commit 47ae8d2

2 files changed

Lines changed: 19 additions & 0 deletions

File tree

src/dqlitewire/messages/responses.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -517,6 +517,11 @@ def decode_body(cls, data: bytes, schema: int = 0) -> "FilesResponse":
517517
offset += consumed
518518
size = decode_uint64(data[offset:])
519519
offset += 8
520+
if offset + size > len(data):
521+
raise DecodeError(
522+
f"FilesResponse file content truncated: expected {size} bytes "
523+
f"at offset {offset}, but only {len(data) - offset} bytes available"
524+
)
520525
content = data[offset : offset + size]
521526
# No padding after content — matches Go's byte-by-byte read.
522527
offset += size

tests/test_messages_responses.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,20 @@ def test_file_count_exceeds_hard_limit(self) -> None:
607607
with pytest.raises(DecodeError, match="File count.*exceeds maximum"):
608608
FilesResponse.decode_body(body)
609609

610+
def test_truncated_file_content_raises(self) -> None:
611+
"""Declared file size larger than available data should raise DecodeError."""
612+
import pytest
613+
614+
from dqlitewire.exceptions import DecodeError
615+
from dqlitewire.types import encode_text, encode_uint64
616+
617+
body = encode_uint64(1) # count=1
618+
body += encode_text("test.db") # filename
619+
body += encode_uint64(4096) # claims 4096 bytes
620+
body += b"\x00" * 100 # but only 100 bytes available
621+
with pytest.raises(DecodeError, match="truncated"):
622+
FilesResponse.decode_body(body)
623+
610624

611625
class TestServersResponse:
612626
def test_empty(self) -> None:

0 commit comments

Comments
 (0)