diff --git a/subsys/bluetooth/audio/bap_base.c b/subsys/bluetooth/audio/bap_base.c index 37d1f72b35e8c..4a7a08acbb7f5 100644 --- a/subsys/bluetooth/audio/bap_base.c +++ b/subsys/bluetooth/audio/bap_base.c @@ -101,6 +101,74 @@ static bool check_pull_ltv(struct net_buf_simple *net_buf) return true; } +static struct bt_bap_base_subgroup *base_pull_subgroup(struct net_buf_simple *net_buf, + uint8_t index) +{ + struct bt_bap_base_subgroup *subgroup = (struct bt_bap_base_subgroup *)net_buf->data; + uint8_t bis_count; + + if (net_buf->len < sizeof(bis_count)) { + LOG_DBG("Invalid BASE length when pulling bis_count: %u", net_buf->size); + + return NULL; + } + + bis_count = base_pull_bis_count(net_buf); + if (!IN_RANGE(bis_count, 1U, BT_ISO_MAX_GROUP_ISO_COUNT)) { + LOG_DBG("Subgroup[%u]: Invalid BIS count: %u", index, bis_count); + + return NULL; + } + + if (net_buf->len < BASE_CODEC_ID_SIZE) { + LOG_DBG("Invalid BASE length when pulling codec: %u", net_buf->size); + + return NULL; + } + + base_pull_codec_id(net_buf, NULL); + + /* Pull CC */ + if (!check_pull_ltv(net_buf)) { + LOG_DBG("Invalid BASE length when pulling CC LTV: %u", net_buf->size); + + return NULL; + } + + /* Pull meta */ + if (!check_pull_ltv(net_buf)) { + LOG_DBG("Invalid BASE length when pulling meta LTV: %u", net_buf->size); + + return NULL; + } + + for (uint8_t i = 0U; i < bis_count; i++) { + uint8_t bis_index; + + if (net_buf->len < sizeof(bis_index)) { + LOG_DBG("Invalid BASE length when pulling bis_index: %u", net_buf->size); + + return NULL; + } + + bis_index = net_buf_simple_pull_u8(net_buf); + if (!IN_RANGE(bis_index, 1U, BT_ISO_BIS_INDEX_MAX)) { + LOG_DBG("Subgroup[%u]: Invalid BIS index: %u", index, bis_index); + + return NULL; + } + + /* Pull BIS CC data */ + if (!check_pull_ltv(net_buf)) { + LOG_DBG("Invalid BASE length when pulling BIS CC LTV: %u", net_buf->size); + + return NULL; + } + } + + return subgroup; +} + const struct bt_bap_base *bt_bap_base_get_base_from_ad(const struct bt_data *ad) { struct bt_uuid_16 broadcast_uuid; @@ -155,66 +223,13 @@ const struct bt_bap_base *bt_bap_base_get_base_from_ad(const struct bt_data *ad) } for (uint8_t i = 0U; i < subgroup_count; i++) { - uint8_t bis_count; - - if (net_buf.len < sizeof(bis_count)) { - LOG_DBG("Invalid BASE length: %u", ad->data_len); - - return NULL; - } + const struct bt_bap_base_subgroup *subgroup = base_pull_subgroup(&net_buf, i); - bis_count = base_pull_bis_count(&net_buf); - if (!IN_RANGE(bis_count, 1U, BT_ISO_MAX_GROUP_ISO_COUNT)) { - LOG_DBG("Subgroup[%u]: Invalid BIS count: %u", i, bis_count); + if (subgroup == NULL) { + LOG_DBG("Subgroup[%u] is invalid", i); return NULL; } - - if (net_buf.len < BASE_CODEC_ID_SIZE) { - LOG_DBG("Invalid BASE length: %u", ad->data_len); - - return NULL; - } - - base_pull_codec_id(&net_buf, NULL); - - /* Pull CC */ - if (!check_pull_ltv(&net_buf)) { - LOG_DBG("Invalid BASE length: %u", ad->data_len); - - return NULL; - } - - /* Pull meta */ - if (!check_pull_ltv(&net_buf)) { - LOG_DBG("Invalid BASE length: %u", ad->data_len); - - return NULL; - } - - for (uint8_t j = 0U; j < bis_count; j++) { - uint8_t bis_index; - - if (net_buf.len < sizeof(bis_index)) { - LOG_DBG("Invalid BASE length: %u", ad->data_len); - - return NULL; - } - - bis_index = net_buf_simple_pull_u8(&net_buf); - if (!IN_RANGE(bis_index, 1U, BT_ISO_BIS_INDEX_MAX)) { - LOG_DBG("Subgroup[%u]: Invalid BIS index: %u", i, bis_index); - - return NULL; - } - - /* Pull BIS CC data */ - if (!check_pull_ltv(&net_buf)) { - LOG_DBG("Invalid BASE length: %u", ad->data_len); - - return NULL; - } - } } return base; @@ -312,7 +327,6 @@ int bt_bap_base_foreach_subgroup(const struct bt_bap_base *base, void *user_data), void *user_data) { - struct bt_bap_base_subgroup *subgroup; struct net_buf_simple net_buf; uint8_t subgroup_count; @@ -333,32 +347,18 @@ int bt_bap_base_foreach_subgroup(const struct bt_bap_base *base, subgroup_count = net_buf_simple_pull_u8(&net_buf); for (uint8_t i = 0U; i < subgroup_count; i++) { - subgroup = (struct bt_bap_base_subgroup *)net_buf.data; - if (!func(subgroup, user_data)) { - LOG_DBG("user stopped parsing"); + const struct bt_bap_base_subgroup *subgroup = base_pull_subgroup(&net_buf, i); - return -ECANCELED; - } - - /* Parse subgroup data to get next subgroup pointer */ - if (subgroup_count > 1) { /* Only parse data if it isn't the last one */ - uint8_t bis_count; - - bis_count = base_pull_bis_count(&net_buf); - base_pull_codec_id(&net_buf, NULL); - - /* Codec config */ - base_pull_ltv(&net_buf, NULL); + if (subgroup == NULL) { + LOG_DBG("Subgroup[%u] is invalid", i); - /* meta */ - base_pull_ltv(&net_buf, NULL); + return -EINVAL; + } - for (uint8_t j = 0U; j < bis_count; j++) { - net_buf_simple_pull_u8(&net_buf); /* index */ + if (!func(subgroup, user_data)) { + LOG_DBG("user stopped parsing"); - /* Codec config */ - base_pull_ltv(&net_buf, NULL); - } + return -ECANCELED; } }