Skip to content

Commit 8dbeb52

Browse files
committed
test(gap): cover 32-bit UUIDs with bit 31 set (signed-shift UB guard)
1 parent 4ea820c commit 8dbeb52

1 file changed

Lines changed: 34 additions & 0 deletions

File tree

tests/test_gap.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,40 @@ def test_parse_advertisement_data_32bit_uuid_malformed_length():
11131113
assert adv.service_uuids == ["efbeadde-0000-1000-8000-00805f9b34fb"]
11141114

11151115

1116+
def test_parse_advertisement_data_32bit_uuid_high_bit_set():
1117+
"""32-bit UUIDs with bit 31 set must decode as the unsigned value.
1118+
1119+
Guards the signed-shift UB fix: ``gap_data[i + 3] << 24`` on an
1120+
``unsigned char`` promotes to (signed) ``int`` in C, so values >= 0x80
1121+
in the top byte would be undefined behavior under Cython without the
1122+
intermediate ``unsigned int`` staging. The decoded UUID must reflect
1123+
the full unsigned 32-bit value, not a sign-extended negative.
1124+
"""
1125+
# length=0x09 (9 = 1 type + 8 bytes), type=0x05 — two 32-bit UUIDs
1126+
# in little-endian: 0xFF112233 -> 33 22 11 FF, 0x80000001 -> 01 00 00 80.
1127+
payload = b"\x09\x05\x33\x22\x11\xff\x01\x00\x00\x80"
1128+
adv = parse_advertisement_data((payload,))
1129+
assert adv.service_uuids == [
1130+
"ff112233-0000-1000-8000-00805f9b34fb",
1131+
"80000001-0000-1000-8000-00805f9b34fb",
1132+
]
1133+
1134+
1135+
def test_parse_advertisement_data_32bit_service_data_high_bit_set():
1136+
"""32-bit service-data UUID with bit 31 set must key on the unsigned value.
1137+
1138+
Same UB guard as the list branch, applied to the
1139+
``TYPE_SERVICE_DATA`` 32-bit decode.
1140+
"""
1141+
# length=0x07 (7 = 1 type + 4 UUID bytes + 2 data bytes), type=0x20
1142+
# UUID little-endian: 0xFF112233 -> 33 22 11 FF; data: AA BB.
1143+
payload = b"\x07\x20\x33\x22\x11\xff\xaa\xbb"
1144+
adv = parse_advertisement_data((payload,))
1145+
assert adv.service_data == {
1146+
"ff112233-0000-1000-8000-00805f9b34fb": b"\xaa\xbb",
1147+
}
1148+
1149+
11161150
def test_parse_advertisement_data_multiple_manufacturer_entries():
11171151
"""Two manufacturer-specific-data AD structs in one packet must both
11181152
survive into the resulting dict, keyed by company ID.

0 commit comments

Comments
 (0)