This is an automated email from the ASF dual-hosted git repository.
xiaoxiang781216 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
The following commit(s) were added to refs/heads/master by this push:
new c95c546c099 wireless/bluetooth: Fix record stride in descriptor
discovery response.
c95c546c099 is described below
commit c95c546c0993a1494cfd7f24c6265e62bef51f7f
Author: Alan Carvalho de Assis <[email protected]>
AuthorDate: Thu Sep 17 10:12:35 2026 -0300
wireless/bluetooth: Fix record stride in descriptor discovery response.
att_find_info_rsp() computed the per-record stride with sizeof(info.i16)
and sizeof(info.i128), but "info" is a union of two pointers, so both
expressions evaluate to the pointer width instead of the size of the
record that the response format selects. The records are 4 octets for a
16-bit UUID and 18 octets for a 128-bit UUID, so the 128-bit path
advanced by 4 (or 8) octets per iteration while reading an 18-octet
record: handles and UUIDs were parsed from the wrong offsets and the walk
ran past the end of the received PDU. On 64-bit builds the 16-bit path
was wrong too.
Take the stride from the record structures, and require the response to
carry whole records before walking it, since the loop advances one record
at a time and a partial trailing record would be parsed as a whole one.
Ref: Core v6.0, Vol 3, Part F, 3.4.3.2 (ATT_FIND_INFORMATION_RSP)
Testing: sim:bluetooth builds with Make, no new warnings. Not yet
exercised at runtime; the scriptable controller that can inject a
malformed Find Information Response is added separately.
Signed-off-by: Alan C. Assis <[email protected]>
Assisted-by: Claude Code Opus 5
---
wireless/bluetooth/bt_gatt.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)
diff --git a/wireless/bluetooth/bt_gatt.c b/wireless/bluetooth/bt_gatt.c
index 4f49fc72c78..5977497b296 100644
--- a/wireless/bluetooth/bt_gatt.c
+++ b/wireless/bluetooth/bt_gatt.c
@@ -952,22 +952,36 @@ static void att_find_info_rsp(FAR struct bt_conn_s *conn,
uint8_t err,
{
case BT_ATT_INFO_16:
uuid.type = BT_UUID_16;
- len = sizeof(info.i16);
+ len = sizeof(struct bt_att_info_16_s);
break;
case BT_ATT_INFO_128:
uuid.type = BT_UUID_128;
- len = sizeof(info.i128);
+ len = sizeof(struct bt_att_info_128_s);
break;
default:
- wlerr("ERROR: Invalid format %u\n", rsp->format);
+ wlerr("ERROR: Invalid format %u\n", rsp->format);
+ goto done;
+ }
+
+ /* The response is the format octet followed by whole records of the
+ * size the format selects. Anything else is malformed and must not be
+ * walked, since the loop below advances by one record at a time.
+ */
+
+ length--;
+
+ if (length < len || (length % len) != 0)
+ {
+ wlerr("ERROR: Invalid info length %u for format %u\n", length,
+ rsp->format);
goto done;
}
/* Parse descriptors found */
- for (length--, pdu = rsp->info; length >= len; length -= len, pdu += len)
+ for (pdu = rsp->info; length >= len; length -= len, pdu += len)
{
FAR const struct bt_gatt_attr_s *attr;