From ede097ab9368b1e132d7827b7b411aa4fd068f9f Mon Sep 17 00:00:00 2001 From: Chris Morgan Date: Sun, 5 Jul 2026 21:30:17 -0400 Subject: [PATCH] NimBLEAttValue.cpp - preserve capacity after realloc failure NimBLEAttValue::append advanced m_capacity immediately after calling realloc. If realloc failed, the original buffer remained allocated but the object advertised a larger capacity than it actually owned. A later append could then skip reallocation and copy past the end of the allocation. Track whether the append actually needs growth and only update m_capacity after the realloc result passes the null check. Appends that fit the existing allocation leave capacity unchanged; failed growth preserves the old capacity invariant. --- src/NimBLEAttValue.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/NimBLEAttValue.cpp b/src/NimBLEAttValue.cpp index 8dbe4866..be769595 100644 --- a/src/NimBLEAttValue.cpp +++ b/src/NimBLEAttValue.cpp @@ -124,9 +124,9 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) { uint8_t* res = m_attr_value; uint16_t new_len = m_attr_len + len; - if (new_len > m_capacity) { - res = static_cast(realloc(m_attr_value, (new_len + 1))); - m_capacity = new_len; + bool grow = new_len > m_capacity; + if (grow) { + res = static_cast(realloc(m_attr_value, (new_len + 1))); } NIMBLE_CPP_DEBUG_ASSERT(res); if (res == nullptr) { @@ -134,6 +134,10 @@ NimBLEAttValue& NimBLEAttValue::append(const uint8_t* value, uint16_t len) { return *this; } + if (grow) { + m_capacity = new_len; + } + # if MYNEWT_VAL(NIMBLE_CPP_ATT_VALUE_TIMESTAMP_ENABLED) time_t t = time(nullptr); # else