@@ -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