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

Commit 77e6cad7 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Andre Eisenbach
Browse files

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)
parent c8265fa4
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -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));
+30 −0
Original line number Diff line number Diff line
@@ -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.
   */
+21 −0
Original line number Diff line number Diff line
@@ -101,3 +101,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