|
6 | 6 | from functools import lru_cache, partial |
7 | 7 | from typing import TYPE_CHECKING |
8 | 8 |
|
9 | | -import cython |
10 | | - |
11 | 9 | BLE_UUID = "0000-1000-8000-00805f9b34fb" |
12 | 10 | _LOGGER = logging.getLogger(__name__) |
13 | 11 |
|
@@ -267,16 +265,21 @@ def _uncached_parse_advertisement_bytes( |
267 | 265 | # per-iteration bounds branch; any 1-3 byte tail is dropped. |
268 | 266 | safe_end = start + ((end - start) & ~3) |
269 | 267 | for i in range(start, safe_end, 4): |
270 | | - # Cast each byte to unsigned int before shifting: in C an |
271 | | - # `unsigned char` operand of `<<` is promoted to (signed) |
272 | | - # `int`, so `gap_data[i + 3] << 24` would be undefined |
273 | | - # behavior when bit 31 is set. Casting keeps the operation |
274 | | - # well-defined on `unsigned int`. |
| 268 | + # Stage each byte through an unsigned-int local (declared in |
| 269 | + # gap.pxd) before shifting: in C an `unsigned char` operand |
| 270 | + # of `<<` is promoted to (signed) `int`, so |
| 271 | + # `gap_data[i + 3] << 24` would be undefined behavior when |
| 272 | + # bit 31 is set. Assigning to the typed local first keeps |
| 273 | + # the shift well-defined on `unsigned int`. |
| 274 | + uuid32_b0 = gap_data[i] |
| 275 | + uuid32_b1 = gap_data[i + 1] |
| 276 | + uuid32_b2 = gap_data[i + 2] |
| 277 | + uuid32_b3 = gap_data[i + 3] |
275 | 278 | uuid32_int = ( |
276 | | - cython.cast(cython.uint, gap_data[i]) |
277 | | - | (cython.cast(cython.uint, gap_data[i + 1]) << 8) |
278 | | - | (cython.cast(cython.uint, gap_data[i + 2]) << 16) |
279 | | - | (cython.cast(cython.uint, gap_data[i + 3]) << 24) |
| 279 | + uuid32_b0 |
| 280 | + | (uuid32_b1 << 8) |
| 281 | + | (uuid32_b2 << 16) |
| 282 | + | (uuid32_b3 << 24) |
280 | 283 | ) |
281 | 284 | service_uuids.append(_cached_uint32_int_as_uuid(uuid32_int)) |
282 | 285 | elif gap_type_num in { |
@@ -309,13 +312,18 @@ def _uncached_parse_advertisement_bytes( |
309 | 312 | continue |
310 | 313 | if service_data is _EMPTY_SERVICE_DATA: |
311 | 314 | service_data = {} |
312 | | - # Cast each byte to unsigned int before shifting to keep the |
313 | | - # << 24 well-defined (see TYPE_32BIT_SERVICE_UUID_* branch above). |
| 315 | + # Stage each byte through an unsigned-int local before shifting |
| 316 | + # to keep the << 24 well-defined (see TYPE_32BIT_SERVICE_UUID_* |
| 317 | + # branch above). |
| 318 | + uuid32_b0 = gap_data[start] |
| 319 | + uuid32_b1 = gap_data[start + 1] |
| 320 | + uuid32_b2 = gap_data[start + 2] |
| 321 | + uuid32_b3 = gap_data[start + 3] |
314 | 322 | uuid32_int = ( |
315 | | - cython.cast(cython.uint, gap_data[start]) |
316 | | - | (cython.cast(cython.uint, gap_data[start + 1]) << 8) |
317 | | - | (cython.cast(cython.uint, gap_data[start + 2]) << 16) |
318 | | - | (cython.cast(cython.uint, gap_data[start + 3]) << 24) |
| 323 | + uuid32_b0 |
| 324 | + | (uuid32_b1 << 8) |
| 325 | + | (uuid32_b2 << 16) |
| 326 | + | (uuid32_b3 << 24) |
319 | 327 | ) |
320 | 328 | service_data[_cached_uint32_int_as_uuid(uuid32_int)] = gap_data[ |
321 | 329 | splice_pos:end |
|
0 commit comments