From: Jakub Pawlowski Date: Fri, 4 Aug 2017 15:56:53 +0000 (-0700) Subject: Advertisement parsing fix for zero padding X-Git-Tag: android-x86-9.0-r1~186^2~4^2~2^2~134^2~7^2~8 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=35a9ea352d;p=android-x86%2Fsystem-bt.git 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 --- diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc index 9630a846a..73d51b779 100644 --- a/stack/btm/btm_ble_gap.cc +++ b/stack/btm/btm_ble_gap.cc @@ -2017,11 +2017,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 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 ac79fbc73..473b97981 100644 --- a/stack/include/advertise_data_parser.h +++ b/stack/include/advertise_data_parser.h @@ -44,6 +44,36 @@ class AdvertiseDataParser { } public: + static void RemoveTrailingZeros(std::vector& 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 7d3db4ce5..643ed34bf 100644 --- a/stack/test/ad_parser_unittest.cc +++ b/stack/test/ad_parser_unittest.cc @@ -127,4 +127,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 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 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 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