@@ -1001,3 +1001,49 @@ def test_parse_advertisement_with_empty_service_data():
10011001 assert adv .service_data == {"0000180a-0000-1000-8000-00805f9b34fb" : b"" }
10021002 assert adv .manufacturer_data == {256 : b"\x50 \x90 \x40 \xa2 " }
10031003 assert adv .tx_power is None
1004+
1005+
1006+ def test_parse_advertisement_data_multiple_128bit_uuids ():
1007+ """Two 128-bit UUIDs packed into a single AD struct must both be returned.
1008+
1009+ Per Core Spec Vol 3 Part C §11, the Complete/Incomplete List of 128-bit
1010+ Service UUIDs AD types carry a list (length = 1 + 16N), not a single UUID.
1011+ Larger packets (scan response / extended advertising) can carry more than one.
1012+ """
1013+ uuid1 = bytes .fromhex ("00112233445566778899aabbccddeeff" )
1014+ uuid2 = bytes .fromhex ("0f1e2d3c4b5a69788796a5b4c3d2e1f0" )
1015+ # Length = 0x21 (33 = 1 type byte + 32 UUID bytes), type = 0x07 (complete list)
1016+ data = b"\x21 \x07 " + uuid1 + uuid2
1017+
1018+ adv = parse_advertisement_data ((data ,))
1019+
1020+ assert adv .local_name is None
1021+ assert adv .service_uuids == [
1022+ # bytes are stored little-endian in BLE — reverse for canonical form
1023+ "ffeeddcc-bbaa-9988-7766-554433221100" ,
1024+ "f0e1d2c3-b4a5-9687-7869-5a4b3c2d1e0f" ,
1025+ ]
1026+ assert adv .service_data == {}
1027+ assert adv .manufacturer_data == {}
1028+ assert adv .tx_power is None
1029+
1030+
1031+ def test_parse_advertisement_data_128bit_uuid_malformed_length ():
1032+ """Malformed 128-bit UUID payloads (length not 1 + 16N) must be skipped.
1033+
1034+ Previously the parser passed the truncated/excess bytes straight to the
1035+ UUID formatter, producing bogus UUID strings (all zeros for short, a
1036+ 64-hex-char garbage string for double-length).
1037+ """
1038+ # Length=0x0a (10 = 1 type + 9 bytes), type=0x07 — only 9 bytes of "UUID"
1039+ short = b"\x0a \x07 " + bytes (9 )
1040+ adv = parse_advertisement_data ((short ,))
1041+ assert adv .service_uuids == []
1042+
1043+ # Length=0x12 (18 = 1 type + 17 bytes), type=0x07 — one valid UUID plus
1044+ # a 1-byte tail that must be ignored, not folded into a second UUID.
1045+ one_and_a_half = (
1046+ b"\x12 \x07 " + bytes .fromhex ("00112233445566778899aabbccddeeff" ) + b"\x42 "
1047+ )
1048+ adv = parse_advertisement_data ((one_and_a_half ,))
1049+ assert adv .service_uuids == ["ffeeddcc-bbaa-9988-7766-554433221100" ]
0 commit comments