From e6e66e8cba05af86bc054b5ba5e5f296d4e128b0 Mon Sep 17 00:00:00 2001 From: Arkadiusz Grzelka Date: Fri, 10 Jul 2026 21:35:15 +0200 Subject: [PATCH 1/2] Raise InvalidPacketError on a truncated ISO data packet HCI_IsoDataPacket.from_bytes() called struct.unpack_from() without checking the buffer length first, so a short packet raised the low-level struct.error instead of the InvalidPacketError the other from_bytes() parsers raise. A 5-byte ISO packet (data_total_length=0, pb_flag=0b00) reproduces it: the SDU info read at offset 5 needs 4 bytes that are not there. Guard each unpack_from with a length check and raise InvalidPacketError, matching HCI_AclDataPacket.from_bytes(). Fixes #955. --- bumble/hci.py | 8 ++++++++ tests/hci_test.py | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/bumble/hci.py b/bumble/hci.py index 30ea1daa5..5dbe2d0d6 100644 --- a/bumble/hci.py +++ b/bumble/hci.py @@ -8174,6 +8174,10 @@ def from_bytes(cls, packet: bytes) -> HCI_IsoDataPacket: packet_status_flag: int | None = None pos = 1 + if len(packet) < pos + 4: + raise InvalidPacketError( + f'ISO data packet too short: {len(packet)} bytes' + ) pdu_info, data_total_length = struct.unpack_from('> 12) & 0b11 @@ -8186,10 +8190,14 @@ def from_bytes(cls, packet: bytes) -> HCI_IsoDataPacket: if ts_flag: if not should_include_sdu_info: logger.warning(f'Timestamp included when pb_flag={bin(pb_flag)}') + if len(packet) < pos + 4: + raise InvalidPacketError('ISO data packet truncated (timestamp)') time_stamp, *_ = struct.unpack_from('> 15) & 1 diff --git a/tests/hci_test.py b/tests/hci_test.py index 0a09584c0..349180e4a 100644 --- a/tests/hci_test.py +++ b/tests/hci_test.py @@ -701,6 +701,16 @@ def test_iso_data_packet(): assert bytes(packet) == data +# ----------------------------------------------------------------------------- +def test_iso_data_packet_too_short(): + # A truncated ISO data packet must raise InvalidPacketError, not the raw + # struct.error from unpack_from. Here pb_flag=0b00 asks for 4 bytes of SDU + # info at offset 5, but the packet ends at offset 5. + data = bytes.fromhex('0561000000') # type + pdu_info(0x0061) + len(0) = 5 bytes + with pytest.raises(hci.InvalidPacketError): + hci.HCI_IsoDataPacket.from_bytes(data) + + # ----------------------------------------------------------------------------- def run_test_events(): test_HCI_Event() From 10d77eeede4b21af7d8171f9220b19b0d96233d3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Grzelka Date: Thu, 13 Aug 2026 15:35:39 +0200 Subject: [PATCH 2/2] style: format with black --- bumble/hci.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bumble/hci.py b/bumble/hci.py index 5dbe2d0d6..55e06b998 100644 --- a/bumble/hci.py +++ b/bumble/hci.py @@ -8175,9 +8175,7 @@ def from_bytes(cls, packet: bytes) -> HCI_IsoDataPacket: pos = 1 if len(packet) < pos + 4: - raise InvalidPacketError( - f'ISO data packet too short: {len(packet)} bytes' - ) + raise InvalidPacketError(f'ISO data packet too short: {len(packet)} bytes') pdu_info, data_total_length = struct.unpack_from('> 12) & 0b11