From e0a6321ba552eb5b05bf1f084e0faa24ae7a72c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 06:07:56 +0000 Subject: [PATCH 01/12] Initial plan From 3322b6e266df0e6dc483c845212532ece9a6dfff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 06:13:52 +0000 Subject: [PATCH 02/12] Tighten whitelist handling and bounds checks Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- src/NimBLEDevice.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index 41da8912..fba84a98 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -718,7 +718,7 @@ bool NimBLEDevice::onWhiteList(const NimBLEAddress& address) { bool NimBLEDevice::whiteListAdd(const NimBLEAddress& address) { if (!NimBLEDevice::onWhiteList(address)) { m_whiteList.push_back(address); - int rc = ble_gap_wl_set(reinterpret_cast(&m_whiteList[0]), m_whiteList.size()); + int rc = ble_gap_wl_set(reinterpret_cast(m_whiteList.data()), m_whiteList.size()); if (rc != 0) { NIMBLE_LOGE(LOG_TAG, "Failed adding to whitelist rc=%d", rc); m_whiteList.pop_back(); @@ -738,14 +738,18 @@ bool NimBLEDevice::whiteListRemove(const NimBLEAddress& address) { for (auto it = m_whiteList.begin(); it < m_whiteList.end(); ++it) { if (*it == address) { m_whiteList.erase(it); - int rc = ble_gap_wl_set(reinterpret_cast(&m_whiteList[0]), m_whiteList.size()); + auto* list = m_whiteList.empty() ? nullptr : reinterpret_cast(m_whiteList.data()); + int rc = ble_gap_wl_set(list, m_whiteList.size()); if (rc != 0) { m_whiteList.push_back(address); NIMBLE_LOGE(LOG_TAG, "Failed removing from whitelist rc=%d", rc); return false; } - std::vector(m_whiteList).swap(m_whiteList); + if (m_whiteList.empty()) { + m_whiteList.shrink_to_fit(); + } + return true; } } @@ -766,7 +770,7 @@ size_t NimBLEDevice::getWhiteListCount() { * @returns The NimBLEAddress at the whitelist index or null address if not found. */ NimBLEAddress NimBLEDevice::getWhiteListAddress(size_t index) { - if (index > m_whiteList.size()) { + if (index >= m_whiteList.size()) { // HA HA AI FOUND AN ERROR! NIMBLE_LOGE(LOG_TAG, "Invalid index; %u", index); return NimBLEAddress{}; } From fc0778f3a45f5e019e89d39b7301c64528b7f661 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 06:15:01 +0000 Subject: [PATCH 03/12] Always shrink whitelist after removal Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- src/NimBLEDevice.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index fba84a98..bbf305be 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -746,9 +746,7 @@ bool NimBLEDevice::whiteListRemove(const NimBLEAddress& address) { return false; } - if (m_whiteList.empty()) { - m_whiteList.shrink_to_fit(); - } + m_whiteList.shrink_to_fit(); return true; } } From b5bde90ef2c430eb7a2ef1d68286fb0a13773498 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 06:15:50 +0000 Subject: [PATCH 04/12] Clarify whitelist removal flow Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- src/NimBLEDevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/NimBLEDevice.cpp b/src/NimBLEDevice.cpp index bbf305be..ee7aacc8 100644 --- a/src/NimBLEDevice.cpp +++ b/src/NimBLEDevice.cpp @@ -747,7 +747,7 @@ bool NimBLEDevice::whiteListRemove(const NimBLEAddress& address) { } m_whiteList.shrink_to_fit(); - return true; + break; } } From 1eb35e8e90536763bd727dce14fc53fabf216f01 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 06:16:24 +0000 Subject: [PATCH 05/12] Update status Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- _codeql_detected_source_root | 1 + 1 file changed, 1 insertion(+) create mode 120000 _codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root new file mode 120000 index 00000000..945c9b46 --- /dev/null +++ b/_codeql_detected_source_root @@ -0,0 +1 @@ +. \ No newline at end of file From e138ad1ac7035592f21c612f8f36c55a1ab55060 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 06:16:51 +0000 Subject: [PATCH 06/12] Remove CodeQL artifact Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- .gitignore | 1 + _codeql_detected_source_root | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 120000 _codeql_detected_source_root diff --git a/.gitignore b/.gitignore index b37ecce2..89963ebe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ docs/doxydocs .development +_codeql_detected_source_root diff --git a/_codeql_detected_source_root b/_codeql_detected_source_root deleted file mode 120000 index 945c9b46..00000000 --- a/_codeql_detected_source_root +++ /dev/null @@ -1 +0,0 @@ -. \ No newline at end of file From 00c3ec42a522b051212b3ff88803038d9d1d0675 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:30:15 +0000 Subject: [PATCH 07/12] Initial plan From 91622d664accb0de9fa0d87960186b7beca81540 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:34:46 +0000 Subject: [PATCH 08/12] Refactor NimBLECharacteristic hot paths minimally Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- src/NimBLECharacteristic.cpp | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 9116a485..2f55f5ea 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -82,14 +82,12 @@ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const char* uuid, uint3 * @return The new BLE descriptor. */ NimBLEDescriptor* NimBLECharacteristic::createDescriptor(const NimBLEUUID& uuid, uint32_t properties, uint16_t maxLen) { - NimBLEDescriptor* pDescriptor = nullptr; if (uuid == NimBLEUUID(static_cast(0x2904))) { NIMBLE_LOGW(LOG_TAG, "0x2904 descriptor should be created with create2904()"); - pDescriptor = create2904(); - } else { - pDescriptor = new NimBLEDescriptor(uuid, properties, maxLen, this); + return create2904(); } + NimBLEDescriptor* pDescriptor = new NimBLEDescriptor(uuid, properties, maxLen, this); addDescriptor(pDescriptor); return pDescriptor; } // createDescriptor @@ -277,9 +275,10 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i const auto subs = getSubscribers(); // make a copy to avoid issues if subscribers change while sending ble_npl_hw_exit_critical(0); - bool chSpecified = connHandle != BLE_HS_CONN_HANDLE_NONE; - bool requireSecure = m_properties & (BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_READ_AUTHOR); + const bool chSpecified = connHandle != BLE_HS_CONN_HANDLE_NONE; + const bool requireSecure = m_properties & (BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_READ_AUTHOR); int rc = chSpecified ? BLE_HS_ENOENT : 0; // if handle specified, assume not found until sent + auto send = isNotification ? ble_gatts_notify_custom : ble_gatts_indicate_custom; // Notify all connected peers unless a specific handle is provided for (const auto& entry : subs) { @@ -306,11 +305,7 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i break; } - if (isNotification) { - rc = ble_gatts_notify_custom(ch, m_handle, om); - } else { - rc = ble_gatts_indicate_custom(ch, m_handle, om); - } + rc = send(ch, m_handle, om); if (rc != 0 || chSpecified) { break; @@ -437,11 +432,7 @@ void NimBLECharacteristic::writeEvent(const uint8_t* val, uint16_t len, NimBLECo * used to define any callbacks for the characteristic. */ void NimBLECharacteristic::setCallbacks(NimBLECharacteristicCallbacks* pCallbacks) { - if (pCallbacks != nullptr) { - m_pCallbacks = pCallbacks; - } else { - m_pCallbacks = &defaultCallback; - } + m_pCallbacks = pCallbacks != nullptr ? pCallbacks : &defaultCallback; } // setCallbacks /** From 68343c91816e46bb85f0e35a156ddcbffecbd439 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:35:12 +0000 Subject: [PATCH 09/12] Address code review naming feedback Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- src/NimBLECharacteristic.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/NimBLECharacteristic.cpp b/src/NimBLECharacteristic.cpp index 2f55f5ea..3eb229db 100644 --- a/src/NimBLECharacteristic.cpp +++ b/src/NimBLECharacteristic.cpp @@ -278,7 +278,7 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i const bool chSpecified = connHandle != BLE_HS_CONN_HANDLE_NONE; const bool requireSecure = m_properties & (BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_READ_AUTHOR); int rc = chSpecified ? BLE_HS_ENOENT : 0; // if handle specified, assume not found until sent - auto send = isNotification ? ble_gatts_notify_custom : ble_gatts_indicate_custom; + auto sendFunc = isNotification ? ble_gatts_notify_custom : ble_gatts_indicate_custom; // Notify all connected peers unless a specific handle is provided for (const auto& entry : subs) { @@ -305,7 +305,7 @@ bool NimBLECharacteristic::sendValue(const uint8_t* value, size_t length, bool i break; } - rc = send(ch, m_handle, om); + rc = sendFunc(ch, m_handle, om); if (rc != 0 || chSpecified) { break; From 1e8ee78bba92f5e52fa308c45325aa9ff7ba63d1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:46:14 +0000 Subject: [PATCH 10/12] Initial plan From c28168ddb7bda2708dd78db5a1a342b5dc50b165 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:50:49 +0000 Subject: [PATCH 11/12] refactor: reduce duplicate work in NimBLEClient::getService Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- src/NimBLEClient.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index 543787b8..bcfba488 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -636,19 +636,21 @@ NimBLERemoteService* NimBLEClient::getService(const char* uuid) { * @return A pointer to the service or nullptr if not found. */ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { - NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuid.toString().c_str()); + const std::string uuidStr = uuid.toString(); + NIMBLE_LOGD(LOG_TAG, ">> getService: uuid: %s", uuidStr.c_str()); for (auto& it : m_svcVec) { if (it->getUUID() == uuid) { - NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuid.toString().c_str()); + NIMBLE_LOGD(LOG_TAG, "<< getService: found the service with uuid: %s", uuidStr.c_str()); return it; } } size_t prevSize = m_svcVec.size(); + auto getNewService = [this, prevSize]() -> NimBLERemoteService* { return m_svcVec.size() > prevSize ? m_svcVec.back() : nullptr; }; if (retrieveServices(&uuid)) { - if (m_svcVec.size() > prevSize) { - return m_svcVec.back(); + if (NimBLERemoteService* svc = getNewService()) { + return svc; } // If the request was successful but 16/32 bit uuid not found @@ -657,8 +659,8 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NimBLEUUID uuid128(uuid); uuid128.to128(); if (retrieveServices(&uuid128)) { - if (m_svcVec.size() > prevSize) { - return m_svcVec.back(); + if (NimBLERemoteService* svc = getNewService()) { + return svc; } } } else { @@ -669,8 +671,8 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { // if the uuid was 128 bit but not of the BLE base type this check will fail if (uuid16.bitSize() == BLE_UUID_TYPE_16) { if (retrieveServices(&uuid16)) { - if (m_svcVec.size() > prevSize) { - return m_svcVec.back(); + if (NimBLERemoteService* svc = getNewService()) { + return svc; } } } From 3c81e213fa6fc5ab3dffe53d6326e58b674f5b84 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Feb 2026 00:52:49 +0000 Subject: [PATCH 12/12] chore: clarify helper naming in NimBLEClient getService Co-authored-by: doudar <17362216+doudar@users.noreply.github.com> --- src/NimBLEClient.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/NimBLEClient.cpp b/src/NimBLEClient.cpp index bcfba488..9e7d11d4 100644 --- a/src/NimBLEClient.cpp +++ b/src/NimBLEClient.cpp @@ -647,9 +647,9 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { } size_t prevSize = m_svcVec.size(); - auto getNewService = [this, prevSize]() -> NimBLERemoteService* { return m_svcVec.size() > prevSize ? m_svcVec.back() : nullptr; }; + auto getLastIfAdded = [this, prevSize]() -> NimBLERemoteService* { return m_svcVec.size() > prevSize ? m_svcVec.back() : nullptr; }; if (retrieveServices(&uuid)) { - if (NimBLERemoteService* svc = getNewService()) { + if (NimBLERemoteService* svc = getLastIfAdded()) { return svc; } @@ -659,7 +659,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { NimBLEUUID uuid128(uuid); uuid128.to128(); if (retrieveServices(&uuid128)) { - if (NimBLERemoteService* svc = getNewService()) { + if (NimBLERemoteService* svc = getLastIfAdded()) { return svc; } } @@ -671,7 +671,7 @@ NimBLERemoteService* NimBLEClient::getService(const NimBLEUUID& uuid) { // if the uuid was 128 bit but not of the BLE base type this check will fail if (uuid16.bitSize() == BLE_UUID_TYPE_16) { if (retrieveServices(&uuid16)) { - if (NimBLERemoteService* svc = getNewService()) { + if (NimBLERemoteService* svc = getLastIfAdded()) { return svc; } }