@@ -252,36 +252,32 @@ def _uncached_parse_advertisement_bytes(
252252 service_uuids = []
253253 # Parse multiple 16-bit UUIDs (each is 2 little-endian bytes).
254254 # Decode inline to an int and look up by int key to skip the
255- # per-iteration bytes-slice allocation. The stride is a power of
256- # two so the bit-AND drops any trailing remainder for malformed
257- # input, lifting the per-iter ``i + 2 <= end`` bounds check out
258- # of the loop body.
259- safe_end = start + ((end - start ) & ~ 1 )
260- for i in range (start , safe_end , 2 ):
261- service_uuids .append (
262- _cached_uint16_int_as_uuid (gap_data [i ] | (gap_data [i + 1 ] << 8 ))
263- )
255+ # per-iteration bytes-slice allocation.
256+ for i in range (start , end , 2 ):
257+ if i + 2 <= end :
258+ service_uuids .append (
259+ _cached_uint16_int_as_uuid (gap_data [i ] | (gap_data [i + 1 ] << 8 ))
260+ )
264261 elif gap_type_num in {
265262 TYPE_32BIT_SERVICE_UUID_COMPLETE ,
266263 TYPE_32BIT_SERVICE_UUID_MORE_AVAILABLE ,
267264 }:
268265 if service_uuids is _EMPTY_SERVICE_UUIDS :
269266 service_uuids = []
270267 # Parse multiple 32-bit UUIDs (each is 4 little-endian bytes).
271- # safe_end trims any malformed remainder ahead of the loop.
272- safe_end = start + ((end - start ) & ~ 3 )
273- for i in range (start , safe_end , 4 ):
274- # Assemble via uint local: in Cython the shift-by-24 of an
275- # unsigned char promotes to signed int and would yield a
276- # negative value when bit 31 is set; assigning to a
277- # cython.uint local recovers the unsigned 32-bit value.
278- uuid32_int = (
279- gap_data [i ]
280- | (gap_data [i + 1 ] << 8 )
281- | (gap_data [i + 2 ] << 16 )
282- | (gap_data [i + 3 ] << 24 )
283- )
284- service_uuids .append (_cached_uint32_int_as_uuid (uuid32_int ))
268+ for i in range (start , end , 4 ):
269+ if i + 4 <= end :
270+ # Assemble via uint local: in Cython the shift-by-24 of an
271+ # unsigned char promotes to signed int and would yield a
272+ # negative value when bit 31 is set; assigning to a
273+ # cython.uint local recovers the unsigned 32-bit value.
274+ uuid32_int = (
275+ gap_data [i ]
276+ | (gap_data [i + 1 ] << 8 )
277+ | (gap_data [i + 2 ] << 16 )
278+ | (gap_data [i + 3 ] << 24 )
279+ )
280+ service_uuids .append (_cached_uint32_int_as_uuid (uuid32_int ))
285281 elif gap_type_num in {
286282 TYPE_128BIT_SERVICE_UUID_MORE_AVAILABLE ,
287283 TYPE_128BIT_SERVICE_UUID_COMPLETE ,
@@ -291,11 +287,11 @@ def _uncached_parse_advertisement_bytes(
291287 # Parse multiple 128-bit UUIDs (each is 16 bytes). The AD length
292288 # may not be a clean multiple of 16 for malformed input — skip
293289 # any trailing remainder rather than emitting a truncated UUID.
294- safe_end = start + (( end - start ) & ~ 15 )
295- for i in range ( start , safe_end , 16 ) :
296- service_uuids .append (
297- _cached_uint128_bytes_as_uuid (gap_data [i : i + 16 ])
298- )
290+ for i in range ( start , end , 16 ):
291+ if i + 16 <= end :
292+ service_uuids .append (
293+ _cached_uint128_bytes_as_uuid (gap_data [i : i + 16 ])
294+ )
299295 elif gap_type_num == TYPE_SERVICE_DATA :
300296 splice_pos = start + 2
301297 if splice_pos > end :
0 commit comments