diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index 8fdf83557d7..883324a8127 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -494,6 +494,8 @@ static int scan_delegator_add_source(struct bt_conn *conn, uint32_t aggregated_bis_syncs = 0; uint32_t broadcast_id; bool bis_sync_requested; + uint16_t total_len; + struct bt_bap_bass_cp_add_src *add_src; /* subtract 1 as the opcode has already been pulled */ if (buf->len < sizeof(struct bt_bap_bass_cp_add_src) - 1) { @@ -501,6 +503,34 @@ static int scan_delegator_add_source(struct bt_conn *conn, return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } + add_src = (void *)(buf->data - 1); + total_len = sizeof(struct bt_bap_bass_cp_add_src) - 1; + for (int i = 0; i < add_src->num_subgroups; i++) { + struct bt_bap_bass_cp_subgroup *subgroup; + uint16_t index = total_len; + + total_len += sizeof(struct bt_bap_bass_cp_subgroup); + if (total_len > buf->len) { + LOG_DBG("Invalid length %u", buf->len); + + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); + } + + subgroup = (void *)&buf->data[index]; + total_len += subgroup->metadata_len; + if (total_len > buf->len) { + LOG_DBG("Invalid length %u", buf->len); + + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); + } + } + + if (total_len != buf->len) { + LOG_DBG("Invalid length %u", buf->len); + + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); + } + internal_state = get_free_recv_state(); if (internal_state == NULL) { LOG_DBG("Could not get free receive state"); @@ -558,11 +588,6 @@ static int scan_delegator_add_source(struct bt_conn *conn, struct bt_bap_bass_subgroup *subgroup = &state->subgroups[i]; uint8_t *metadata; - if (buf->len < (sizeof(subgroup->bis_sync) + sizeof(subgroup->metadata_len))) { - LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); - } - internal_state->requested_bis_sync[i] = net_buf_simple_pull_le32(buf); if (internal_state->requested_bis_sync[i] && @@ -596,13 +621,6 @@ static int scan_delegator_add_source(struct bt_conn *conn, subgroup->metadata_len = net_buf_simple_pull_u8(buf); - if (buf->len < subgroup->metadata_len) { - LOG_DBG("Invalid length %u", buf->size); - - return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); - } - - if (subgroup->metadata_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) { LOG_WRN("Metadata too long %u/%u", subgroup->metadata_len, CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE); @@ -615,11 +633,6 @@ static int scan_delegator_add_source(struct bt_conn *conn, subgroup->metadata_len); } - if (buf->len != 0) { - LOG_DBG("Invalid length %u", buf->size); - return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); - } - /* The active flag shall be set before any application callbacks, so that any calls for the * receive state can be processed */ @@ -676,6 +689,8 @@ static int scan_delegator_mod_src(struct bt_conn *conn, uint8_t pa_sync; uint32_t aggregated_bis_syncs = 0; bool bis_sync_change_requested; + uint16_t total_len; + struct bt_bap_bass_cp_mod_src *mod_src; /* subtract 1 as the opcode has already been pulled */ if (buf->len < sizeof(struct bt_bap_bass_cp_mod_src) - 1) { @@ -684,6 +699,34 @@ static int scan_delegator_mod_src(struct bt_conn *conn, return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); } + mod_src = (void *)(buf->data - 1); + total_len = sizeof(struct bt_bap_bass_cp_mod_src) - 1; + for (int i = 0; i < mod_src->num_subgroups; i++) { + struct bt_bap_bass_cp_subgroup *subgroup; + uint16_t index = total_len; + + total_len += sizeof(struct bt_bap_bass_cp_subgroup); + if (total_len > buf->len) { + LOG_DBG("Invalid length %u", buf->len); + + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); + } + + subgroup = (void *)&buf->data[index]; + total_len += subgroup->metadata_len; + if (total_len > buf->len) { + LOG_DBG("Invalid length %u", buf->len); + + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); + } + } + + if (total_len != buf->len) { + LOG_DBG("Invalid length %u", buf->len); + + return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); + } + src_id = net_buf_simple_pull_u8(buf); internal_state = bass_lookup_src_id(src_id); @@ -718,11 +761,6 @@ static int scan_delegator_mod_src(struct bt_conn *conn, uint32_t old_bis_sync_req; uint8_t *metadata; - if (buf->len < (sizeof(subgroup->bis_sync) + sizeof(subgroup->metadata_len))) { - LOG_DBG("Invalid length %u", buf->len); - return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); - } - old_bis_sync_req = internal_state->requested_bis_sync[i]; internal_state->requested_bis_sync[i] = net_buf_simple_pull_le32(buf); @@ -754,11 +792,6 @@ static int scan_delegator_mod_src(struct bt_conn *conn, subgroup->metadata_len = net_buf_simple_pull_u8(buf); - if (buf->len < subgroup->metadata_len) { - LOG_DBG("Invalid length %u", buf->len); - return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); - } - if (subgroup->metadata_len > CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE) { LOG_WRN("Metadata too long %u/%u", subgroup->metadata_len, CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE); @@ -771,12 +804,6 @@ static int scan_delegator_mod_src(struct bt_conn *conn, subgroup->metadata_len); } - if (buf->len != 0) { - LOG_DBG("Invalid length %u", buf->size); - - return BT_GATT_ERR(BT_ATT_ERR_WRITE_REQ_REJECTED); - } - /* All input has been validated; update receive state and check for changes */ state = &internal_state->state;