This fixes the calculation of available buffer space in bt_gatt_server_send_notification and sends pending notifications immediately when there is no more room to add a notification. Previously there was a buffer overflow caused by incorrect calculation of available buffer space: data->offset can equal data->len from a previous call to this function, leading (data->len - data->offset) to underflow after data->offset += 2. --- src/shared/gatt-server.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/shared/gatt-server.c b/src/shared/gatt-server.c index 970c35f94..e7155f16a 100644 --- a/src/shared/gatt-server.c +++ b/src/shared/gatt-server.c @@ -1700,20 +1700,34 @@ bool bt_gatt_server_send_notification(struct bt_gatt_server *server, if (!server || (length && !value)) return false; - if (multiple) + if (multiple) { data = server->nfy_mult; + /* Flush buffered data, if this request hits buffer size limit */ + if (data && data->offset > 0 && data->len - data->offset < 4 + length) { + if (server->nfy_mult->id) + timeout_remove(server->nfy_mult->id); + notify_multiple(server); + data = NULL; + } + } + if (!data) { data = new0(struct nfy_mult_data, 1); data->len = bt_att_get_mtu(server->att) - 1; data->pdu = malloc(data->len); } + if (multiple) { + if (data->len - data->offset < 4 + length) + return false; + } else { + if (data->len - data->offset < 2 + length) + return false; + } + put_le16(handle, data->pdu + data->offset); data->offset += 2; - - length = MIN(data->len - data->offset, length); - if (multiple) { put_le16(length, data->pdu + data->offset); data->offset += 2; -- 2.25.1