summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Pawlowski <jpawlowski@google.com>2017-08-04 08:56:53 -0700
committerAndre Eisenbach <eisenbach@google.com>2017-08-07 21:10:59 +0000
commit436058ee3f52419fde558068a77222a67153e40d (patch)
tree013e954e4eeb4bdb250ba23337caace3ba9fc4c4
parenta8ba0bd7c8758cc7250a76db343558cbccd315cd (diff)
downloadandroid_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.cc7
-rw-r--r--stack/include/advertise_data_parser.h30
-rw-r--r--stack/test/ad_parser_unittest.cc21
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