CVE-2023-45781 AI-generated analysis
platform/packages/modules/Bluetooth, system/main/shim (GD shim utilities, GAP/advertising data parsing)
Adds a bounds check in parse_gap_data (system/main/shim/utils.cc). If a GAP data element's length byte points past the end of raw_data, parsing now stops instead of copying out of bounds.
Root cause
parse_gap_data walks raw_data as a sequence of length-prefixed GAP elements. For each element it read len = raw_data[offset], built iterators begin = raw_data.begin() + offset and end = begin + len + 1, and copied [begin, end) into a new vector. The only check was the loop condition offset < raw_data.size(). The per-element length was never compared against the remaining bytes. So a len larger than the remaining buffer produced an end iterator past raw_data.end(), and the copy (std::vector range construction) read out of bounds.
How the fix works
- system/main/shim/utils.cc:parse_gap_data: after reading len, the fix adds `if (offset + len + 1 > raw_data.size()) break;` before computing begin/end and copying. If the element (1 length byte plus len payload bytes) would run past the end of raw_data, the loop exits. The truncated element is not copied, not parsed by hci::GapData::Parse and not pushed to output.
- The arithmetic is done in size_t (offset is size_t; len is a uint8_t that gets promoted), so offset + len + 1 cannot wrap for realistic sizes.
Completeness
- The check covers the only copy in parse_gap_data. It comes before the iterator computation, so no out-of-range iterator is formed. Well-formed elements before the bad one are still returned.
- An element with len == 0 passes the check and yields a 1-byte copy. offset then advances by 1, so there is no infinite loop.
- The fix only validates the length, not the contents. hci::GapData::Parse is still called on the copied bytes, and its own handling of the data is not shown in the material.
- Only this one function changes. The material does not show other length-prefixed parsers in the shim, so whether sibling paths are covered cannot be judged from it.
Behavior changes
- GAP data parsing now stops silently at the first element whose declared length overruns the buffer. That element and all bytes after it are dropped from output. No error is logged or returned.
Per major
- Android 14: Same fix: commit 423c0285e5ee in android-security-14.0.0_r3 (cherry-pick of 0d7e3d8fd963, marked Ignore-AOSP-First). At android-security-14.0.0_r29 all 5 lines of the patched region are present.
- Android 15: Not affected per the bulletin. The patched region is present (5/5 lines) at android-security-15.0.0_r17.
- Android 16: Not affected per the bulletin. The patched region is present (5/5 lines) at android-security-16.0.0_r8.
- Android 17: Not affected per the bulletin. The patched region is present (5/5 lines) at android-security-17.0.0_r1.
Unknowns
- Who calls parse_gap_data, and whether raw_data comes from remote peers (reachability and attack surface).
- The Android 13 fix commit (the bulletin lists 13 as affected, but the commit is not in the material).
- How hci::GapData::Parse behaves on short or malformed element contents.
- Whether the fix is also delivered through a Bluetooth module update (not shown in the material).