Skip to content

Commit 6265928

Browse files
bluetoothbotclaude
andauthored
test(gap): cover malformed 16/32-bit UUID lists and multi-manufacturer (#231)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 7a9ebf1 commit 6265928

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

tests/test_gap.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,3 +1070,62 @@ def test_parse_advertisement_data_tx_power_multibyte_rejected():
10701070
data = (b"\x03\x0a\x00\x80",)
10711071
adv = parse_advertisement_data(data)
10721072
assert adv.tx_power is None
1073+
1074+
1075+
def test_parse_advertisement_data_16bit_uuid_malformed_length():
1076+
"""16-bit UUID list with a trailing odd byte must drop the remainder, not
1077+
emit a UUID built from a 1-byte slice.
1078+
1079+
Mirrors the 128-bit malformed-length protection (PR #226) for the
1080+
16-bit list branch.
1081+
"""
1082+
# length=0x06 (6 = 1 type + 5 bytes), type=0x03 — two valid UUIDs plus a
1083+
# 1-byte tail that must not be folded into a third UUID.
1084+
payload = b"\x06\x03\xaa\xbb\xcc\xdd\xee"
1085+
adv = parse_advertisement_data((payload,))
1086+
assert adv.service_uuids == [
1087+
"0000bbaa-0000-1000-8000-00805f9b34fb",
1088+
"0000ddcc-0000-1000-8000-00805f9b34fb",
1089+
]
1090+
1091+
# length=0x04 (4 = 1 type + 3 bytes), type=0x02 — one UUID + 1 trailing
1092+
# byte; the trailing byte must not be folded into a second UUID.
1093+
one_and_a_half = b"\x04\x02\x11\x22\x33"
1094+
adv = parse_advertisement_data((one_and_a_half,))
1095+
assert adv.service_uuids == ["00002211-0000-1000-8000-00805f9b34fb"]
1096+
1097+
1098+
def test_parse_advertisement_data_32bit_uuid_malformed_length():
1099+
"""32-bit UUID list with a tail < 4 bytes must drop the remainder.
1100+
1101+
Mirrors the 128-bit malformed-length protection (PR #226) for the
1102+
32-bit list branch.
1103+
"""
1104+
# length=0x08 (8 = 1 type + 7 bytes), type=0x05 — one valid 32-bit UUID
1105+
# plus a 3-byte tail.
1106+
payload = b"\x08\x05\x11\x22\x33\x44\xaa\xbb\xcc"
1107+
adv = parse_advertisement_data((payload,))
1108+
assert adv.service_uuids == ["44332211-0000-1000-8000-00805f9b34fb"]
1109+
1110+
# length=0x06 (6 = 1 type + 5 bytes), type=0x04 — one UUID + 1 trailing
1111+
# byte; the trailing byte must not be folded into a second UUID.
1112+
one_and_a_quarter = b"\x06\x04\xde\xad\xbe\xef\x99"
1113+
adv = parse_advertisement_data((one_and_a_quarter,))
1114+
assert adv.service_uuids == ["efbeadde-0000-1000-8000-00805f9b34fb"]
1115+
1116+
1117+
def test_parse_advertisement_data_multiple_manufacturer_entries():
1118+
"""Two manufacturer-specific-data AD structs in one packet must both
1119+
survive into the resulting dict, keyed by company ID.
1120+
1121+
BLE Core Spec Vol 3 Part C §11 permits the Manufacturer Specific Data
1122+
AD type to appear more than once in a single advertisement.
1123+
"""
1124+
# First MSD: company 0x004C (Apple), payload \x01\x02
1125+
# Second MSD: company 0x0059 (Nordic), payload \x03\x04\x05
1126+
payload = b"\x05\xff\x4c\x00\x01\x02" + b"\x06\xff\x59\x00\x03\x04\x05"
1127+
adv = parse_advertisement_data((payload,))
1128+
assert adv.manufacturer_data == {
1129+
0x004C: b"\x01\x02",
1130+
0x0059: b"\x03\x04\x05",
1131+
}

0 commit comments

Comments
 (0)