This is an automated email from the ASF dual-hosted git repository.

janc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit e584b4ed9169bf502b8dd473fdba78aac5b48a61
Author: Oleksandr Nychyporuk <[email protected]>
AuthorDate: Mon Feb 9 17:28:38 2026 +0200

    nimble/host: Fix Read By Type and Find By Type Val hardcoded buff limits
    
    ble_att_svr_build_read_type_rsp() used a fixed 19-byte stack buffer for 
reading
    attribute values, causing BLE_ATT_ERR_UNLIKELY for any value exceeding 19 
bytes.
    Per Core Spec 3.4.4.2, the limit should be min(ATT_MTU - 4, 253).
    Similarly, ble_att_svr_fill_type_value() used a 16-byte buffer, failing to 
match attributes
    with longer values.
    
    Replace both flat buffers with a reusable mbuf, reading via 
ble_att_svr_read() directly
    and truncating per spec. This aligns with the approach already used in the 
code.
---
 nimble/host/src/ble_att_svr.c | 74 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 61 insertions(+), 13 deletions(-)

diff --git a/nimble/host/src/ble_att_svr.c b/nimble/host/src/ble_att_svr.c
index 8fdf0e845..535b4b350 100644
--- a/nimble/host/src/ble_att_svr.c
+++ b/nimble/host/src/ble_att_svr.c
@@ -1089,8 +1089,9 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
                             uint16_t mtu, uint8_t *out_att_err)
 {
     struct ble_att_svr_entry *ha;
-    uint8_t buf[16];
+    struct os_mbuf *attr_om;
     uint16_t attr_len;
+    uint16_t req_val_len;
     uint16_t first;
     uint16_t prev;
     int any_entries;
@@ -1099,6 +1100,11 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
     first = 0;
     prev = 0;
     rc = 0;
+    attr_om = NULL;
+
+    /* Length of the attribute value in the request. */
+    req_val_len = OS_MBUF_PKTLEN(rxom) -
+                  sizeof(struct ble_att_find_type_value_req);
 
     /* Iterate through the attribute list, keeping track of the current
      * matching group.  For each attribute entry, determine if data needs to be
@@ -1141,15 +1147,31 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
          * determine if this attribute matches.
          */
         if (ble_uuid_cmp(ha->ha_uuid, &attr_type.u) == 0) {
-            rc = ble_att_svr_read_flat(conn_handle, ha, 0, sizeof buf, buf,
-                                       &attr_len, out_att_err);
+            /* Lazily allocate a temporary mbuf for reading attribute values. 
*/
+            if (attr_om == NULL) {
+                attr_om = ble_hs_mbuf_l2cap_pkt();
+                if (attr_om == NULL) {
+                    *out_att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
+                    rc = BLE_HS_ENOMEM;
+                    goto done;
+                }
+            } else {
+                os_mbuf_adj(attr_om, OS_MBUF_PKTLEN(attr_om));
+            }
+
+            /* Read attribute value into temporary mbuf. */
+            rc = ble_att_svr_read(conn_handle, ha, 0, attr_om, out_att_err);
             if (rc != 0) {
                 goto done;
             }
-            /* value is at the end of req */
-            rc = os_mbuf_cmpf(rxom, sizeof(struct ble_att_find_type_value_req),
-                              buf, attr_len);
-            if (rc == 0) {
+
+            attr_len = OS_MBUF_PKTLEN(attr_om);
+
+            /* Compare attribute value with the value from the request. */
+            if (attr_len == req_val_len &&
+                os_mbuf_cmpm(rxom,
+                             sizeof(struct ble_att_find_type_value_req),
+                             attr_om, 0, attr_len) == 0) {
                 first = ha->ha_handle_id;
                 prev = ha->ha_handle_id;
             }
@@ -1170,6 +1192,8 @@ ble_att_svr_fill_type_value(uint16_t conn_handle,
     }
 
 done:
+    os_mbuf_free_chain(attr_om);
+
     any_entries = OS_MBUF_PKTHDR(txom)->omp_len >
                   BLE_ATT_FIND_TYPE_VALUE_RSP_BASE_SZ;
     if (rc == 0 && !any_entries) {
@@ -1293,9 +1317,10 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, 
uint16_t cid,
     struct ble_att_read_type_rsp *rsp;
     struct ble_att_svr_entry *entry;
     struct os_mbuf *txom;
+    struct os_mbuf *attr_om;
     uint16_t attr_len;
+    uint16_t max_attr_len;
     uint16_t mtu;
-    uint8_t buf[19];
     int entry_written;
     int txomlen;
     int prev_attr_len;
@@ -1306,6 +1331,7 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, 
uint16_t cid,
     *err_handle = start_handle;
     entry_written = 0;
     prev_attr_len = 0;
+    attr_om = NULL;
 
     /* Just reuse the request buffer for the response. */
     txom = *rxom;
@@ -1326,6 +1352,12 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, 
uint16_t cid,
 
     mtu = ble_att_mtu_by_cid(conn_handle, cid);
 
+    /* Per Core Spec: max attribute value length is min(ATT_MTU - 4, 253). */
+    max_attr_len = mtu - 4;
+    if (max_attr_len > 253) {
+        max_attr_len = 253;
+    }
+
     /* Find all matching attributes, writing a record for each. */
     entry = NULL;
     while (1) {
@@ -1336,15 +1368,29 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, 
uint16_t cid,
         }
 
         if (entry->ha_handle_id >= start_handle) {
-            rc = ble_att_svr_read_flat(conn_handle, entry, 0, sizeof buf, buf,
-                                       &attr_len, att_err);
+            /* Lazily allocate a temporary mbuf for reading attribute values. 
*/
+            if (attr_om == NULL) {
+                attr_om = ble_hs_mbuf_l2cap_pkt();
+                if (attr_om == NULL) {
+                    *att_err = BLE_ATT_ERR_INSUFFICIENT_RES;
+                    *err_handle = entry->ha_handle_id;
+                    rc = BLE_HS_ENOMEM;
+                    goto done;
+                }
+            } else {
+                os_mbuf_adj(attr_om, OS_MBUF_PKTLEN(attr_om));
+            }
+
+            /* Read attribute value into temporary mbuf. */
+            rc = ble_att_svr_read(conn_handle, entry, 0, attr_om, att_err);
             if (rc != 0) {
                 *err_handle = entry->ha_handle_id;
                 goto done;
             }
 
-            if (attr_len > mtu - 4) {
-                attr_len = mtu - 4;
+            attr_len = OS_MBUF_PKTLEN(attr_om);
+            if (attr_len > max_attr_len) {
+                attr_len = max_attr_len;
             }
 
             if (prev_attr_len == 0) {
@@ -1367,12 +1413,14 @@ ble_att_svr_build_read_type_rsp(uint16_t conn_handle, 
uint16_t cid,
             }
 
             data->handle = htole16(entry->ha_handle_id);
-            memcpy(data->value, buf, attr_len);
+            os_mbuf_copydata(attr_om, 0, attr_len, data->value);
             entry_written = 1;
         }
     }
 
 done:
+    os_mbuf_free_chain(attr_om);
+
     if (!entry_written) {
         /* No matching attributes. */
         if (*att_err == 0) {

Reply via email to