Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 47aa262f authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by android-build-merger
Browse files

Advertisement parsing fix for zero padding

am: 819b843f

Change-Id: I59bf8524b2c95c5f8c7f4261166057078dd25b7c
parents c1625851 819b843f
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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<uint8_t> const& adv_data =
      is_start ? cache.Set(addr_type, bda, std::move(tmp))
               : cache.Append(addr_type, bda, std::move(tmp));
+30 −0
Original line number Diff line number Diff line
@@ -44,6 +44,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.
   */
+21 −0
Original line number Diff line number Diff line
@@ -128,3 +128,24 @@ TEST(AdvertiseDataParserTest, GetFieldByType) {
  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