@@ -247,47 +247,50 @@ def _uncached_parse_advertisement_bytes(
247247 if service_uuids is _EMPTY_SERVICE_UUIDS :
248248 service_uuids = []
249249 # Parse multiple 16-bit UUIDs (each is 2 little-endian bytes).
250- # Decode inline to an int and look up by int key to skip the
251- # per-iteration bytes-slice allocation .
252- for i in range ( start , end , 2 ):
253- if i + 2 <= end :
254- service_uuids .append (
255- _cached_uint16_int_as_uuid (gap_data [i ] | (gap_data [i + 1 ] << 8 ))
256- )
250+ # Truncate to a multiple-of-2 endpoint so the loop body has no
251+ # per-iteration bounds branch; any odd tail is dropped .
252+ safe_end = start + (( end - start ) & ~ 1 )
253+ for i in range ( start , safe_end , 2 ) :
254+ service_uuids .append (
255+ _cached_uint16_int_as_uuid (gap_data [i ] | (gap_data [i + 1 ] << 8 ))
256+ )
257257 elif gap_type_num in {
258258 TYPE_32BIT_SERVICE_UUID_COMPLETE ,
259259 TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE ,
260260 }:
261261 if service_uuids is _EMPTY_SERVICE_UUIDS :
262262 service_uuids = []
263263 # Parse multiple 32-bit UUIDs (each is 4 little-endian bytes).
264- for i in range (start , end , 4 ):
265- if i + 4 <= end :
266- # Assemble via uint local: in Cython the shift-by-24 of an
267- # unsigned char promotes to signed int and would yield a
268- # negative value when bit 31 is set; assigning to a
269- # cython.uint local recovers the unsigned 32-bit value.
270- uuid32_int = (
271- gap_data [i ]
272- | (gap_data [i + 1 ] << 8 )
273- | (gap_data [i + 2 ] << 16 )
274- | (gap_data [i + 3 ] << 24 )
275- )
276- service_uuids .append (_cached_uint32_int_as_uuid (uuid32_int ))
264+ # Truncate to a multiple-of-4 endpoint so the loop body has no
265+ # per-iteration bounds branch; any 1-3 byte tail is dropped.
266+ safe_end = start + ((end - start ) & ~ 3 )
267+ for i in range (start , safe_end , 4 ):
268+ # Assemble via uint local: in Cython the shift-by-24 of an
269+ # unsigned char promotes to signed int and would yield a
270+ # negative value when bit 31 is set; assigning to a
271+ # cython.uint local recovers the unsigned 32-bit value.
272+ uuid32_int = (
273+ gap_data [i ]
274+ | (gap_data [i + 1 ] << 8 )
275+ | (gap_data [i + 2 ] << 16 )
276+ | (gap_data [i + 3 ] << 24 )
277+ )
278+ service_uuids .append (_cached_uint32_int_as_uuid (uuid32_int ))
277279 elif gap_type_num in {
278280 TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE ,
279281 TYPE_128BIT_SERVICE_UUID_COMPLETE ,
280282 }:
281283 if service_uuids is _EMPTY_SERVICE_UUIDS :
282284 service_uuids = []
283- # Parse multiple 128-bit UUIDs (each is 16 bytes). The AD length
284- # may not be a clean multiple of 16 for malformed input — skip
285- # any trailing remainder rather than emitting a truncated UUID.
286- for i in range (start , end , 16 ):
287- if i + 16 <= end :
288- service_uuids .append (
289- _cached_uint128_bytes_as_uuid (gap_data [i : i + 16 ])
290- )
285+ # Parse multiple 128-bit UUIDs (each is 16 bytes). Truncate to a
286+ # multiple-of-16 endpoint so the loop body has no per-iteration
287+ # bounds branch; any trailing remainder is dropped rather than
288+ # emitting a truncated UUID.
289+ safe_end = start + ((end - start ) & ~ 15 )
290+ for i in range (start , safe_end , 16 ):
291+ service_uuids .append (
292+ _cached_uint128_bytes_as_uuid (gap_data [i : i + 16 ])
293+ )
291294 elif gap_type_num == TYPE_SERVICE_DATA :
292295 splice_pos = start + 2
293296 if splice_pos > total_length or splice_pos > end :
0 commit comments