From 65fb26b5197d6cf1bd262eab98d52b159f89db9f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 19 Dec 2022 09:21:23 -1000 Subject: [PATCH] fix: handle zero padding in adv data (#9) --- src/bluetooth_data_tools/gap.py | 7 ++++++- tests/test_gap.py | 35 +++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/bluetooth_data_tools/gap.py b/src/bluetooth_data_tools/gap.py index 8262737..394e8ef 100644 --- a/src/bluetooth_data_tools/gap.py +++ b/src/bluetooth_data_tools/gap.py @@ -69,10 +69,15 @@ def decode_advertisement_data( ) -> Iterable[tuple[BLEGAPType, bytes]]: """Decode a BLE GAP AD structure.""" offset = 0 - while offset < len(encoded_struct): + total_length = len(encoded_struct) + while offset < total_length: try: length = encoded_struct[offset] if not length: + if offset + 2 < total_length: + # Maybe zero padding + offset += 1 + continue return type_ = encoded_struct[offset + 1] if not type_: diff --git a/tests/test_gap.py b/tests/test_gap.py index c98b8c0..1db8efc 100644 --- a/tests/test_gap.py +++ b/tests/test_gap.py @@ -198,3 +198,38 @@ def test_parse_advertisement_data_128bit_service_data(): assert adv.service_data == {"00090401-0052-036b-3206-ff0a050a021a": b"\x04"} assert adv.manufacturer_data == {} assert adv.tx_power is None + + +def test_parse_advertisement_data_zero_padded(): + data = [ + bytes.fromhex( + "02.01.06.0E.FF.69.09.FA.62.0F.CF.2D.F2.DA.0F" + ".00.22.04.00.09.16.3D.FD.63.C0.56.00.22.04".replace(".", "") + ) + ] + + adv = parse_advertisement_data(data) + + assert adv.local_name is None + assert adv.service_uuids == [] + assert adv.service_data == { + "0000fd3d-0000-1000-8000-00805f9b34fb": b'c\xc0V\x00"\x04' + } + assert adv.manufacturer_data == {2409: b'\xfab\x0f\xcf-\xf2\xda\x0f\x00"\x04'} + assert adv.tx_power is None + + +def test_parse_advertisement_data_zero_padded_scan_included(): + data = [ + b"\x02\x01\x06\t\xffY\x00\xfe\x024\x9e\xa6\xba\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x07\x1b\xc5\xd5\xa5\x02\x00\xb8" + b'\x9f\xe6\x11M"\x00\r\xa2\xcb\x06\x16\x00\rH\x10\x00\x00\x00\x00\x00\x00\x00' + ] + + adv = parse_advertisement_data(data) + + assert adv.local_name is None + assert adv.service_uuids == ["cba20d00-224d-11e6-9fb8-0002a5d5c51b"] + assert adv.service_data == {"00000d00-0000-1000-8000-00805f9b34fb": b"H\x10\x00"} + assert adv.manufacturer_data == {89: b"\xfe\x024\x9e\xa6\xba"} + assert adv.tx_power is None