From a38b404c348b1e615c44ef97f6d2594ec7b80912 Mon Sep 17 00:00:00 2001 From: Alan Carvalho de Assis Date: Thu, 17 Sep 2026 10:12:35 -0300 Subject: [PATCH] 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 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 4f49fc72c78b7..5977497b29694 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;