diff options
author | Jakub Pawlowski <jpawlowski@google.com> | 2017-08-04 08:56:53 -0700 |
---|---|---|
committer | Andre Eisenbach <eisenbach@google.com> | 2017-08-07 21:10:59 +0000 |
commit | 436058ee3f52419fde558068a77222a67153e40d (patch) | |
tree | 013e954e4eeb4bdb250ba23337caace3ba9fc4c4 | |
parent | a8ba0bd7c8758cc7250a76db343558cbccd315cd (diff) | |
download | android_system_bt-436058ee3f52419fde558068a77222a67153e40d.tar.gz android_system_bt-436058ee3f52419fde558068a77222a67153e40d.tar.bz2 android_system_bt-436058ee3f52419fde558068a77222a67153e40d.zip |
Advertisement parsing fix for zero padding
When AD data is zero padded, and Scan Response is appended at end, data
becomes invalid. Instead, zero paddning must be removed first.
Test: AdvertiseDataParserTest.RemoveTrailingZeros
Bug: 38489707
Change-Id: I229ca3db6c92bc06bc1429e72412417010721063
Merged-In: I229ca3db6c92bc06bc1429e72412417010721063
(cherry picked from commit 35a9ea352d59e6d261eba1254814f7238e3ed022)
-rw-r--r-- | stack/btm/btm_ble_gap.cc | 7 | ||||
-rw-r--r-- | stack/include/advertise_data_parser.h | 30 | ||||
-rw-r--r-- | stack/test/ad_parser_unittest.cc | 21 |
3 files changed, 56 insertions, 2 deletions
diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc index be12e6117..fe093e2bd 100644 --- a/stack/btm/btm_ble_gap.cc +++ b/stack/btm/btm_ble_gap.cc @@ -2103,11 +2103,14 @@ static void btm_ble_process_adv_pkt_cont( bool is_scannable = ble_evt_type_is_scannable(evt_type); bool is_scan_resp = ble_evt_type_is_scan_resp(evt_type); + bool is_start = + ble_evt_type_is_legacy(evt_type) && is_scannable && !is_scan_resp; + + if (is_start) AdvertiseDataParser::RemoveTrailingZeros(tmp); + // We might have send scan request to this device before, but didn't get the // response. In such case make sure data is put at start, not appended to // already existing data. - bool is_start = - ble_evt_type_is_legacy(evt_type) && is_scannable && !is_scan_resp; std::vector<uint8_t> const& adv_data = is_start ? cache.Set(addr_type, bda, std::move(tmp)) : cache.Append(addr_type, bda, std::move(tmp)); diff --git a/stack/include/advertise_data_parser.h b/stack/include/advertise_data_parser.h index 1c5f99f8f..0efac4f57 100644 --- a/stack/include/advertise_data_parser.h +++ b/stack/include/advertise_data_parser.h @@ -22,6 +22,36 @@ class AdvertiseDataParser { public: + static void RemoveTrailingZeros(std::vector<uint8_t>& ad) { + size_t position = 0; + + size_t ad_len = ad.size(); + while (position != ad_len) { + uint8_t len = ad[position]; + + // A field length of 0 would be invalid as it should at least contain the + // EIR field type. However, some existing devices send zero padding at the + // end of advertisement. If this is the case, cut the zero padding from + // end of the packet. Otherwise i.e. gluing scan response to advertise + // data will result in data with zero padding in the middle. + if (len == 0) { + size_t zeros_start = position; + for (size_t i = position + 1; i < ad_len; i++) { + if (ad[i] != 0) return; + } + + ad.erase(ad.begin() + zeros_start, ad.end()); + return; + } + + if (position + len >= ad_len) { + return; + } + + position += len + 1; + } + } + /** * Return true if this |ad| represent properly formatted advertising data. */ diff --git a/stack/test/ad_parser_unittest.cc b/stack/test/ad_parser_unittest.cc index 3202130a3..ab6df5606 100644 --- a/stack/test/ad_parser_unittest.cc +++ b/stack/test/ad_parser_unittest.cc @@ -100,4 +100,25 @@ TEST(AdvertiseDataParserTest, GetFieldByType) { data = AdvertiseDataParser::GetFieldByType(data1, 0x03, &p_length); EXPECT_EQ(nullptr, data); EXPECT_EQ(0, p_length); +} + +// This test makes sure that RemoveTrailingZeros is working correctly. It does +// run the RemoveTrailingZeros for ad data, then glue scan response at end of +// it, and checks that the resulting data is good. +TEST(AdvertiseDataParserTest, RemoveTrailingZeros) { + std::vector<uint8_t> podo_ad_data{ + 0x02, 0x01, 0x02, 0x11, 0x06, 0x66, 0x9a, 0x0c, 0x20, 0x00, 0x08, + 0x37, 0xa8, 0xe5, 0x11, 0x81, 0x8b, 0xd0, 0xf0, 0xf0, 0xf0, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + const std::vector<uint8_t> podo_scan_resp{ + 0x03, 0x19, 0x00, 0x80, 0x09, 0x09, 0x50, 0x6f, 0x64, 0x6f, 0x51, + 0x35, 0x56, 0x47, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + AdvertiseDataParser::RemoveTrailingZeros(podo_ad_data); + + std::vector<uint8_t> glued(podo_ad_data); + glued.insert(glued.end(), podo_ad_data.begin(), podo_ad_data.end()); + + EXPECT_TRUE(AdvertiseDataParser::IsValid(glued)); }
\ No newline at end of file |