@@ -231,47 +231,50 @@ def _uncached_parse_advertisement_bytes(
231231 if service_uuids is _EMPTY_SERVICE_UUIDS :
232232 service_uuids = []
233233 # Parse multiple 16-bit UUIDs (each is 2 little-endian bytes).
234- # Decode inline to an int and look up by int key to skip the
235- # per-iteration bytes-slice allocation .
236- for i in range ( start , end , 2 ):
237- if i + 2 <= end :
238- service_uuids .append (
239- _cached_uint16_int_as_uuid (gap_data [i ] | (gap_data [i + 1 ] << 8 ))
240- )
234+ # Truncate to a multiple-of-2 endpoint so the loop body has no
235+ # per-iteration bounds branch; any odd tail is dropped .
236+ safe_end = start + (( end - start ) & ~ 1 )
237+ for i in range ( start , safe_end , 2 ) :
238+ service_uuids .append (
239+ _cached_uint16_int_as_uuid (gap_data [i ] | (gap_data [i + 1 ] << 8 ))
240+ )
241241 elif gap_type_num in {
242242 TYPE_32BIT_SERVICE_UUID_COMPLETE ,
243243 TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE ,
244244 }:
245245 if service_uuids is _EMPTY_SERVICE_UUIDS :
246246 service_uuids = []
247247 # Parse multiple 32-bit UUIDs (each is 4 little-endian bytes).
248- for i in range (start , end , 4 ):
249- if i + 4 <= end :
250- # Assemble via uint local: in Cython the shift-by-24 of an
251- # unsigned char promotes to signed int and would yield a
252- # negative value when bit 31 is set; assigning to a
253- # cython.uint local recovers the unsigned 32-bit value.
254- uuid32_int = (
255- gap_data [i ]
256- | (gap_data [i + 1 ] << 8 )
257- | (gap_data [i + 2 ] << 16 )
258- | (gap_data [i + 3 ] << 24 )
259- )
260- service_uuids .append (_cached_uint32_int_as_uuid (uuid32_int ))
248+ # Truncate to a multiple-of-4 endpoint so the loop body has no
249+ # per-iteration bounds branch; any 1-3 byte tail is dropped.
250+ safe_end = start + ((end - start ) & ~ 3 )
251+ for i in range (start , safe_end , 4 ):
252+ # Assemble via uint local: in Cython the shift-by-24 of an
253+ # unsigned char promotes to signed int and would yield a
254+ # negative value when bit 31 is set; assigning to a
255+ # cython.uint local recovers the unsigned 32-bit value.
256+ uuid32_int = (
257+ gap_data [i ]
258+ | (gap_data [i + 1 ] << 8 )
259+ | (gap_data [i + 2 ] << 16 )
260+ | (gap_data [i + 3 ] << 24 )
261+ )
262+ service_uuids .append (_cached_uint32_int_as_uuid (uuid32_int ))
261263 elif gap_type_num in {
262264 TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE ,
263265 TYPE_128BIT_SERVICE_UUID_COMPLETE ,
264266 }:
265267 if service_uuids is _EMPTY_SERVICE_UUIDS :
266268 service_uuids = []
267- # Parse multiple 128-bit UUIDs (each is 16 bytes). The AD length
268- # may not be a clean multiple of 16 for malformed input — skip
269- # any trailing remainder rather than emitting a truncated UUID.
270- for i in range (start , end , 16 ):
271- if i + 16 <= end :
272- service_uuids .append (
273- _cached_uint128_bytes_as_uuid (gap_data [i : i + 16 ])
274- )
269+ # Parse multiple 128-bit UUIDs (each is 16 bytes). Truncate to a
270+ # multiple-of-16 endpoint so the loop body has no per-iteration
271+ # bounds branch; any trailing remainder is dropped rather than
272+ # emitting a truncated UUID.
273+ safe_end = start + ((end - start ) & ~ 15 )
274+ for i in range (start , safe_end , 16 ):
275+ service_uuids .append (
276+ _cached_uint128_bytes_as_uuid (gap_data [i : i + 16 ])
277+ )
275278 elif gap_type_num == TYPE_SERVICE_DATA :
276279 splice_pos = start + 2
277280 if splice_pos > total_length or splice_pos > end :
0 commit comments