Skip to content

nimble/host: Fix ATT Read By Type and Find By Type Value responses limited by hardcoded buffer sizes#2171

Open
nychyporuk wants to merge 2 commits intoapache:masterfrom
nychyporuk:issue_1881
Open

nimble/host: Fix ATT Read By Type and Find By Type Value responses limited by hardcoded buffer sizes#2171
nychyporuk wants to merge 2 commits intoapache:masterfrom
nychyporuk:issue_1881

Conversation

@nychyporuk
Copy link
Contributor

@nychyporuk nychyporuk commented Feb 9, 2026

Problem
The original issue is described here: #1881

When reading a characteristic by UUID (ATT_READ_BY_TYPE_REQ), attribute values longer than 19 bytes cause the server to respond with BLE_ATT_ERR_UNLIKELY instead of returning the data. Similarly, Find By Type Value (ATT_FIND_BY_TYPE_VALUE_REQ) fails to match attributes with values longer than 16 bytes.
Both issues stem from hardcoded stack buffers passed to ble_att_svr_read_flat(), which returns BLE_ATT_ERR_UNLIKELY when the attribute value exceeds max_len:

  • ble_att_svr_build_read_type_rsp: uint8_t buf[19] - caps Read By Type at 19 bytes
  • ble_att_svr_fill_type_value: uint8_t buf[16] - caps Find By Type Value comparison at 16 bytes

Per Core Spec v6.0, Section 3.4.4.2, the maximum attribute value in ATT_READ_BY_TYPE_RSP is min(ATT_MTU - 4, 253) octets. The 19-byte limit corresponds to the default MTU of 23 and was never updated to respect the negotiated MTU.
To the application's access_cb, the read appears successful - there is no indication that the client will receive an error.

Proposed Fix
Replace both hardcoded flat buffers with a lazily-allocated reusable mbuf per function call. Attribute values are read via ble_att_svr_read() directly into the mbuf, then:
Read By Type: truncated to min(MTU - 4, 253) per spec and copied into the response. Values longer than the limit are truncated gracefully instead of causing errors.
Find By Type Value: compared against the request value using os_mbuf_cmpm() (mbuf-to-mbuf), with no size restriction.
The mbuf is allocated lazily on first matching entry, reset each iteration with os_mbuf_adj(), and freed in cleanup. This avoids unnecessary allocation when no attributes match the requested handle range, preserving correct behavior under OOM conditions

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.
Verify that Read By Type and Find By Type Value correctly handle
attribute values exceeding the old hardcoded buffer limits.

Tests cover full value return, MTU-based truncation, large value
matching, value mismatch, and length mismatch.

Also raise the 16-byte limit in the Find By Type Value test helper
to BLE_ATT_ATTR_MAX_LEN.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

host size/M Medium PR size/S Small PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants