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

Commit 8a754ad9 authored by Michal Belusiak's avatar Michal Belusiak Committed by Michal Belusiak (xWF)
Browse files

le_periodic_sync_manager: Prevent from operation on invalid iterator

Bug: 354890418
Test: atest PeriodicSyncManagerTest
Flag: Exempt, crash prevent covered with unit tests
Change-Id: I0441e46e0826a5a2fc0499058e1f165dbdd66708
parent c433ae62
Loading
Loading
Loading
Loading
+43 −14
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ public:
    log::debug("[PSync]: handle = {}", handle);
    auto periodic_sync = GetEstablishedSyncFromHandle(handle);
    if (periodic_sync == periodic_syncs_.end()) {
      log::error("[PSync]: invalid index for handle {}", handle);
      log::error("[PSync]: index not found for handle {}", handle);
      le_scanning_interface_->EnqueueCommand(
              hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(handle),
              handler_->BindOnce(check_complete<LePeriodicAdvertisingTerminateSyncCompleteView>));
@@ -125,7 +125,7 @@ public:
    log::debug("[PSync]");
    auto periodic_sync = GetSyncFromAddressAndSid(address, adv_sid);
    if (periodic_sync == periodic_syncs_.end()) {
      log::error("[PSync]:Invalid index for sid={}", adv_sid);
      log::error("[PSync]: index not found for address={} and SID={:04X}", address, adv_sid);
      return;
    }

@@ -211,15 +211,24 @@ public:
    log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
    auto status = status_view.GetStatus();
    if (status != ErrorCode::SUCCESS) {
      if (pending_sync_requests_.empty()) {
        log::error("pending_sync_requests_ empty");
        return;
      }
      auto& request = pending_sync_requests_.front();
      request.sync_timeout_alarm.Cancel();
      log::warn("Got a Command status {}, status {}, SID={:04X}, bd_addr={}",
                OpCodeText(view.GetCommandOpCode()), ErrorCodeText(status), request.advertiser_sid,
                request.address_with_type);

      uint8_t adv_sid = request.advertiser_sid;
      AddressWithType address_with_type = request.address_with_type;
      auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, adv_sid);
      auto sync =
              GetSyncFromAddressWithTypeAndSid(request.address_with_type, request.advertiser_sid);
      if (sync == periodic_syncs_.end()) {
        log::error("[PSync]: index not found for address={} and SID={:04X}",
                   request.address_with_type, request.advertiser_sid);
        AdvanceRequest();
        return;
      }
      callbacks_->OnPeriodicSyncStarted(sync->request_id, (uint8_t)status, 0, sync->advertiser_sid,
                                        request.address_with_type, 0, 0);
      periodic_syncs_.erase(sync);
@@ -237,6 +246,10 @@ public:
    log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()");
    auto status = status_view.GetStatus();
    if (status != ErrorCode::SUCCESS) {
      if (pending_sync_requests_.empty()) {
        log::error("pending_sync_requests_ empty");
        return;
      }
      auto& request = pending_sync_requests_.front();
      request.sync_timeout_alarm.Cancel();
      log::warn("Got a Command complete {}, status {}, SID={:04X}, bd_addr={}",
@@ -308,11 +321,13 @@ public:
        break;
    }

    auto periodic_sync = GetSyncFromAddressWithTypeAndSid(
            AddressWithType(event_view.GetAdvertiserAddress(), temp_address_type),
    auto address_with_temp_type =
            AddressWithType(event_view.GetAdvertiserAddress(), temp_address_type);
    auto periodic_sync = GetSyncFromAddressWithTypeAndSid(address_with_temp_type,
                                                          event_view.GetAdvertisingSid());
    if (periodic_sync == periodic_syncs_.end()) {
      log::warn("[PSync]: Invalid address and sid for sync established");
      log::warn("[PSync]: index not found for address={} and SID={:04X}", address_with_temp_type,
                event_view.GetAdvertisingSid());
      if (event_view.GetStatus() == ErrorCode::SUCCESS) {
        log::warn("Terminate sync");
        le_scanning_interface_->EnqueueCommand(
@@ -410,17 +425,24 @@ public:
  }

  void OnStartSyncTimeout() {
    if (pending_sync_requests_.empty()) {
      log::error("pending_sync_requests_ empty");
      return;
    }
    auto& request = pending_sync_requests_.front();
    log::warn("sync timeout SID={:04X}, bd_addr={}", request.advertiser_sid,
              request.address_with_type);
    uint8_t adv_sid = request.advertiser_sid;
    AddressWithType address_with_type = request.address_with_type;
    auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, adv_sid);
    le_scanning_interface_->EnqueueCommand(
            hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(),
            handler_->BindOnceOn(
                    this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus<
                                  LePeriodicAdvertisingCreateSyncCancelCompleteView>));
    auto sync = GetSyncFromAddressWithTypeAndSid(request.address_with_type, request.advertiser_sid);
    if (sync == periodic_syncs_.end()) {
      log::error("[PSync]: index not found for address={} and SID={:04X}",
                 request.address_with_type, request.advertiser_sid);
      return;
    }
    int status = static_cast<int>(ErrorCode::ADVERTISING_TIMEOUT);
    callbacks_->OnPeriodicSyncStarted(sync->request_id, status, 0, sync->advertiser_sid,
                                      request.address_with_type, 0, 0);
@@ -513,8 +535,6 @@ private:
                    PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) |
            static_cast<uint8_t>(
                    PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_TWO_US_SLOTS);
    auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, sid);
    sync->sync_state = PERIODIC_SYNC_STATE_PENDING;
    AdvertisingAddressType advertisingAddressType =
            static_cast<AdvertisingAddressType>(address_with_type.GetAddressType());
    le_scanning_interface_->EnqueueCommand(
@@ -540,6 +560,15 @@ private:
    }
    request.busy = true;
    request.sync_timeout_alarm.Cancel();

    auto sync = GetSyncFromAddressWithTypeAndSid(request.address_with_type, request.advertiser_sid);
    if (sync == periodic_syncs_.end()) {
      log::warn("[PSync]: index not found for address={} and SID={:04X}", request.address_with_type,
                request.advertiser_sid);
      AdvanceRequest();
      return;
    }
    sync->sync_state = PERIODIC_SYNC_STATE_PENDING;
    HandleStartSyncRequest(request.advertiser_sid, request.address_with_type, request.skip,
                           request.sync_timeout);
    request.sync_timeout_alarm.Schedule(
+61 −0
Original line number Diff line number Diff line
@@ -753,6 +753,67 @@ TEST_F_WITH_FLAGS(PeriodicSyncManagerTest,
  sync_handler();
}

TEST_F(PeriodicSyncManagerTest, onStartSyncTimeout_callWithoutPendingRequestsAndPeriodicSyncs) {
  periodic_sync_manager_->OnStartSyncTimeout();
  sync_handler();
}

TEST_F(PeriodicSyncManagerTest, onStartSyncTimeout_callWithoutPeriodicSyncs) {
  uint16_t sync_handle = 0x12;
  Address address;
  Address::FromString("00:11:22:33:44:55", address);
  AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);

  uint8_t advertiser_sid_1 = 0x02;
  int request_id_1 = 0x01;
  PeriodicSyncStates request{
          .request_id = request_id_1,
          .advertiser_sid = advertiser_sid_1,
          .address_with_type = address_with_type,
          .sync_handle = sync_handle,
          .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
  };
  ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
  periodic_sync_manager_->StartSync(request, 0x04, 0x0A);

  // First timeout to erase periodic_syncs_
  periodic_sync_manager_->OnStartSyncTimeout();
  // Second to actual check
  periodic_sync_manager_->OnStartSyncTimeout();
  sync_handler();
}

TEST_F(PeriodicSyncManagerTest,
       handlePeriodicAdvertisingCreateSyncStatus_callWithoutPeriodicSyncs) {
  uint16_t sync_handle = 0x12;
  Address address;
  Address::FromString("00:11:22:33:44:55", address);
  AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);

  int request_id_1 = 0x01;
  uint8_t advertiser_sid_1 = 0x02;
  PeriodicSyncStates request{
          .request_id = request_id_1,
          .advertiser_sid = advertiser_sid_1,
          .address_with_type = address_with_type,
          .sync_handle = sync_handle,
          .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
  };
  ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
  periodic_sync_manager_->StartSync(request, 0x04, 0x0A);

  // Timeout to erase periodic_syncs_
  periodic_sync_manager_->OnStartSyncTimeout();

  auto packet =
          test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
  LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
  test_le_scanning_interface_->CommandStatusCallback(
          LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::MEMORY_CAPACITY_EXCEEDED,
                                                               0x00));
  sync_handler();
}

TEST_F(PeriodicSyncManagerTest, handle_periodic_advertising_report_test) {
  uint16_t sync_handle = 0x12;
  uint8_t advertiser_sid = 0x02;