diff --git a/components/bt/host/bluedroid/api/esp_avrc_api.c b/components/bt/host/bluedroid/api/esp_avrc_api.c index ff4f601c5d..8c7bfcced7 100644 --- a/components/bt/host/bluedroid/api/esp_avrc_api.c +++ b/components/bt/host/bluedroid/api/esp_avrc_api.c @@ -624,6 +624,10 @@ esp_err_t esp_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_rn_ return ESP_ERR_NOT_SUPPORTED; } + if (param == NULL) { + return ESP_ERR_INVALID_ARG; + } + btc_msg_t msg; msg.sig = BTC_SIG_API_CALL; msg.pid = BTC_PID_AVRC_TG; diff --git a/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c b/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c index d886f593d1..bdb1cd6f85 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_ca_act.c @@ -48,18 +48,24 @@ static UINT8 get_rcb_idx(tBTA_AV_RCB *p_rcb) return (p_rcb - &bta_av_cb.rcb[0]); } -static void get_peer_bd_addr(tBTA_AV_RCB *p_rcb, BD_ADDR out_addr) +static BOOLEAN get_peer_bd_addr(tBTA_AV_RCB *p_rcb, BD_ADDR out_addr) { /* check if this rcb is related to a scb */ if (p_rcb->shdl && p_rcb->shdl <= BTA_AV_NUM_STRS) { tBTA_AV_SCB *p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1]; - bdcpy(out_addr, p_scb->peer_addr); + if (p_scb != NULL) { + bdcpy(out_addr, p_scb->peer_addr); + return TRUE; + } } /* else, try get peer addr from lcb */ else if (p_rcb->lidx && p_rcb->lidx <= BTA_AV_NUM_LINKS + 1) { bdcpy(out_addr, bta_av_cb.lcb[p_rcb->lidx-1].addr); + return TRUE; } + + return FALSE; } static void report_data_event(BT_HDR *pkt, UINT8 *p_data, UINT16 data_len, BOOLEAN final) @@ -131,7 +137,8 @@ static void close_goepc_and_disconnect(tBTA_AV_RCB *p_rcb) tBTA_AV_DATA *p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA)); if (p_data == NULL) { - assert(0); + APPL_TRACE_ERROR("close_goepc_and_disconnect ENOMEM"); + return; } p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT; p_data->hdr.layer_specific = get_rcb_idx(p_rcb); @@ -154,6 +161,11 @@ void bta_av_ca_goep_event_handler(UINT16 handle, UINT8 event, tGOEPC_MSG *p_msg) { tBTA_AV_DATA *p_data = NULL; UINT16 rcb_idx; + + if (p_msg == NULL) { + goto error; + } + if (!find_rcb_idx_by_goep_handle(handle, &rcb_idx)) { /* can not find a rcb, go error */ goto error; @@ -161,7 +173,9 @@ void bta_av_ca_goep_event_handler(UINT16 handle, UINT8 event, tGOEPC_MSG *p_msg) if (event == GOEPC_RESPONSE_EVT || event == GOEPC_OPENED_EVT || event == GOEPC_CLOSED_EVT) { p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA)); - assert(p_data != NULL); + if (p_data == NULL) { + goto error; + } } switch (event) @@ -208,7 +222,7 @@ error: if (p_data != NULL) { osi_free(p_data); } - if (event == GOEPC_RESPONSE_EVT && p_msg->response.pkt != NULL) { + if (event == GOEPC_RESPONSE_EVT && p_msg && p_msg->response.pkt != NULL) { osi_free(p_msg->response.pkt); } if (event != GOEPC_CLOSED_EVT) { @@ -225,13 +239,19 @@ void bta_av_ca_api_open(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) /* reuse the security mask store in bta_av_cb, when support multi connection, this may need change */ svr.l2cap.sec_mask = bta_av_cb.sec_mask; p_rcb->cover_art_max_rx = p_data->api_ca_open.mtu; - get_peer_bd_addr(p_rcb, svr.l2cap.addr); + if (!get_peer_bd_addr(p_rcb, svr.l2cap.addr)) { + goto error; + } if (GOEPC_Open(&svr, bta_av_ca_goep_event_handler, &p_rcb->cover_art_goep_hdl) != GOEP_SUCCESS) { /* open failed */ - if ((p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA))) == NULL) { - assert(0); - } + goto error; + } + + return; + +error: + if ((p_data = (tBTA_AV_DATA *) osi_malloc(sizeof(tBTA_AV_DATA))) != NULL) { p_data->hdr.event = BTA_AV_CA_GOEP_DISCONNECT_EVT; p_data->hdr.layer_specific = get_rcb_idx(p_rcb); p_data->ca_disconnect.reason = BT_STATUS_FAIL; @@ -271,7 +291,7 @@ void bta_av_ca_api_get(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) break; default: /* should not go here */ - assert(0); + goto error; break; } image_handle_to_utf16(p_data->api_ca_get.image_handle, image_handle_utf16); @@ -307,19 +327,21 @@ void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) { case OBEX_HEADER_ID_BODY: /* actually,END_OF_BODY should not in this continue response */ - case OBEX_HEADER_ID_END_OF_BODY: + case OBEX_HEADER_ID_END_OF_BODY: { + UINT16 hdr_len = OBEX_GetHeaderLength(header); + UINT16 seg_len = (hdr_len >= 3) ? (UINT16)(hdr_len - 3) : 0; if (body_data == NULL) { /* first body header */ body_data = header + 3; /* skip opcode, length */ - body_data_len = OBEX_GetHeaderLength(header) - 3; - } - else { + body_data_len = seg_len; + } else { /* another body header found */ report_data_event(NULL, body_data, body_data_len, FALSE); body_data = header + 3; /* skip opcode, length */ - body_data_len = OBEX_GetHeaderLength(header) - 3; + body_data_len = seg_len; } break; + } default: break; } @@ -395,19 +417,21 @@ void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data) { /* actually, BODY should not in this final response */ case OBEX_HEADER_ID_BODY: - case OBEX_HEADER_ID_END_OF_BODY: + case OBEX_HEADER_ID_END_OF_BODY: { + UINT16 hdr_len = OBEX_GetHeaderLength(header); + UINT16 seg_len = (hdr_len >= 3) ? (UINT16)(hdr_len - 3) : 0; if (body_data == NULL) { /* first body header */ body_data = header + 3; /* skip opcode, length */ - body_data_len = OBEX_GetHeaderLength(header) - 3; - } - else { + body_data_len = seg_len; + } else { /* another body header found */ report_data_event(NULL, body_data, body_data_len, FALSE); body_data = header + 3; /* skip opcode, length */ - body_data_len = OBEX_GetHeaderLength(header) - 3; + body_data_len = seg_len; } break; + } default: break; } diff --git a/components/bt/host/bluedroid/bta/av/bta_av_ca_sm.c b/components/bt/host/bluedroid/bta/av/bta_av_ca_sm.c index 4a9d4e7c58..750daab09e 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_ca_sm.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_ca_sm.c @@ -153,6 +153,18 @@ void bta_av_ca_sm_execute(tBTA_AV_RCB *p_rcb, UINT16 event, tBTA_AV_DATA *p_data { tBTA_AV_CA_ST_TBL state_table; UINT8 action; + + if (p_rcb == NULL || + p_rcb->cover_art_state >= (sizeof(bta_av_ca_st_tbl) / sizeof(bta_av_ca_st_tbl[0]))) { + APPL_TRACE_WARNING("ca_sm_exec: EINVAL p_rcb"); + return; + } + + if (event < BTA_AV_CA_FIRST_SM_EVT || event > BTA_AV_CA_LAST_SM_EVT) { + APPL_TRACE_WARNING("ca_sm_exec: evt %u OOR", event); + return; + } + /* look up the state table for the current state */ state_table = bta_av_ca_st_tbl[p_rcb->cover_art_state]; diff --git a/components/bt/host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c b/components/bt/host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c index bc2226e7b2..d1902b7e1a 100644 --- a/components/bt/host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c +++ b/components/bt/host/bluedroid/btc/profile/std/avrc/bta_avrc_co.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +25,8 @@ #include "btc_avrc.h" #if BTC_AV_INCLUDED + +#define AVRC_TG_SUPPORTED_CMD_ARRAY_SIZE (8) /******************************************************************************* ** ** Function bta_avrc_co_cmd_allowed @@ -37,10 +39,13 @@ *******************************************************************************/ BOOLEAN bta_avrc_co_cmd_allowed(tBTA_AV_RC rc_id) { - if (rc_id >= BTA_AV_VENDOR) { + if (rc_id >= BTA_AV_VENDOR || (rc_id >> 4) >= AVRC_TG_SUPPORTED_CMD_ARRAY_SIZE) { return FALSE; } const uint16_t *rc_cmd = btc_avrc_tg_get_supported_command(); + if (rc_cmd == NULL) { + return FALSE; + } if (rc_cmd[rc_id >> 4] & ((uint16_t)1 << (rc_id & 0x0F))) { return TRUE; } else { @@ -52,7 +57,7 @@ BOOLEAN bta_avrc_co_cmd_allowed(tBTA_AV_RC rc_id) ** ** Function bta_avrc_co_rn_evt_cap ** - ** Description get the event notifcation capabilities on AVRCP target + ** Description get the event notification capabilities on AVRCP target ** ** Returns number of event_ids supported ** @@ -65,7 +70,7 @@ UINT8 bta_avrc_co_rn_evt_cap(UINT8 *event_ids) UINT16 event_bits = btc_avrc_tg_get_rn_supported_evt(); UINT8 count = 0; - for (UINT8 i = 0; i < 16; ++i, event_bits >>= 1) { + for (UINT8 i = 0; i < AVRC_CAP_MAX_NUM_EVT_ID; ++i, event_bits >>= 1) { if (event_bits & 0x01) { event_ids[count++] = i; } diff --git a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c index 95279b4e38..df5f63e114 100644 --- a/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c +++ b/components/bt/host/bluedroid/btc/profile/std/avrc/btc_avrc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2026 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -145,6 +145,9 @@ bool btc_avrc_tg_check_rn_supported_evt(uint16_t evt_set) bool btc_avrc_tg_rn_evt_supported(uint8_t event_id) { + if (event_id > MAX_RC_NOTIFICATIONS) { + return false; + } uint16_t event_bits = s_rn_supported_evt; return ((event_bits >> event_id) & 0x0001) ? true : false; @@ -152,6 +155,9 @@ bool btc_avrc_tg_rn_evt_supported(uint8_t event_id) bool btc_avrc_ct_rn_evt_supported(uint8_t event_id) { + if (event_id > MAX_RC_NOTIFICATIONS) { + return false; + } uint16_t event_bits = cs_ct_rn_supported_evt; return ((event_bits >> event_id) & 0x0001) ? true : false; @@ -198,8 +204,10 @@ void btc_avrc_arg_deep_copy(btc_msg_t *msg, void *p_dest, void *p_src) dst->ca_get_img.image_descriptor = (uint8_t *)osi_malloc(len); if (dst->ca_get_img.image_descriptor) { memcpy(dst->ca_get_img.image_descriptor, src->ca_get_img.image_descriptor, len); + dst->ca_get_img.image_descriptor_len = len; } else { BTC_TRACE_ERROR("%s %d no mem\n", __FUNCTION__, msg->act); + dst->ca_get_img.image_descriptor_len = 0; } break; #endif @@ -361,23 +369,26 @@ static void send_metamsg_rsp (UINT8 rc_handle, UINT8 label, tBTA_AV_CODE code, /* if response is for register_notification, make sure the rc has actually registered for this */ if ((p_meta_rsp->rsp.pdu == AVRC_PDU_REGISTER_NOTIFICATION) && (code == AVRC_RSP_CHANGED)) { UINT8 event_id = p_meta_rsp->reg_notif.event_id; - BOOLEAN notify = (btc_rc_cb.rc_connected) && (btc_rc_cb.rc_ntf[event_id - 1].registered); + if (event_id == 0 || event_id > MAX_RC_NOTIFICATIONS) { + BTC_TRACE_WARNING("snd_metamsg_rsp: EINVAL reg_ntf evt_id 0x%x", event_id); + } else { + BOOLEAN notify = (btc_rc_cb.rc_connected) && (btc_rc_cb.rc_ntf[event_id - 1].registered); - /* de-register this notification for a CHANGED response */ - btc_rc_cb.rc_ntf[event_id - 1].registered = FALSE; - BTC_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d deregistered", __FUNCTION__, - btc_rc_cb.rc_handle, event_id); - if (notify) { - BT_HDR *p_msg = NULL; - tAVRC_STS status = AVRC_BldResponse(btc_rc_cb.rc_handle, p_meta_rsp, &p_msg); + /* de-register this notification for a CHANGED response */ + btc_rc_cb.rc_ntf[event_id - 1].registered = FALSE; + BTC_TRACE_DEBUG("%s rc_handle: %d. event_id: 0x%02d deregistered", __FUNCTION__, + btc_rc_cb.rc_handle, event_id); + if (notify) { + BT_HDR *p_msg = NULL; + tAVRC_STS status = AVRC_BldResponse(btc_rc_cb.rc_handle, p_meta_rsp, &p_msg); - if (status == AVRC_STS_NO_ERROR) { - BTC_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d", - __FUNCTION__, btc_rc_cb.rc_handle, event_id); - BTA_AvMetaRsp(btc_rc_cb.rc_handle, btc_rc_cb.rc_ntf[event_id - 1].label, ctype, p_msg); - } else { - BTC_TRACE_WARNING("%s failed to build metamsg response. status: 0x%02x", - __FUNCTION__, status); + if (status == AVRC_STS_NO_ERROR) { + BTC_TRACE_DEBUG("%s Sending notification to rc_handle: %d. event_id: 0x%02d", + __FUNCTION__, btc_rc_cb.rc_handle, event_id); + BTA_AvMetaRsp(btc_rc_cb.rc_handle, btc_rc_cb.rc_ntf[event_id - 1].label, ctype, p_msg); + } else { + BTC_TRACE_WARNING("snd_metamsg_rsp: bld_rsp failed stat: 0x%02x", status); + } } } } else { @@ -536,6 +547,9 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) return; } + BD_ADDR peer_bda; + memcpy(peer_bda, btc_rc_cb.rc_addr, sizeof(BD_ADDR)); + tBTA_AV_FEAT rc_features = btc_rc_cb.rc_features; // clean up the state @@ -567,15 +581,15 @@ static void handle_rc_disconnect (tBTA_AV_RC_CLOSE *p_rc_close) esp_avrc_ct_cb_param_t param; memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); param.conn_stat.connected = false; - memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t)); + memcpy(param.conn_stat.remote_bda, peer_bda, sizeof(esp_bd_addr_t)); btc_avrc_ct_cb_to_app(ESP_AVRC_CT_CONNECTION_STATE_EVT, ¶m); } if (btc_avrc_tg_init_p()) { esp_avrc_tg_cb_param_t param; - memset(¶m, 0, sizeof(esp_avrc_ct_cb_param_t)); + memset(¶m, 0, sizeof(esp_avrc_tg_cb_param_t)); param.conn_stat.connected = false; - memcpy(param.conn_stat.remote_bda, btc_rc_cb.rc_addr, sizeof(esp_bd_addr_t)); + memcpy(param.conn_stat.remote_bda, peer_bda, sizeof(esp_bd_addr_t)); btc_avrc_tg_cb_to_app(ESP_AVRC_TG_CONNECTION_STATE_EVT, ¶m); } } @@ -586,6 +600,7 @@ static void handle_rc_attributes_rsp (tAVRC_MSG_VENDOR *vendor_msg) int attr_index = 5; int attr_length = 0; uint32_t attr_id = 0; + esp_avrc_ct_cb_param_t *param = NULL; if (!vendor_msg || !vendor_msg->p_vendor_data || (vendor_msg->vendor_len < AVRC_GET_ELEMENT_ATTR_RSP_SIZE_MIN)) { @@ -597,27 +612,33 @@ static void handle_rc_attributes_rsp (tAVRC_MSG_VENDOR *vendor_msg) return; } - esp_avrc_ct_cb_param_t param[attr_count]; - memset(¶m[0], 0, sizeof(esp_avrc_ct_cb_param_t) * attr_count); + + param = (esp_avrc_ct_cb_param_t *)osi_calloc(attr_count * sizeof(esp_avrc_ct_cb_param_t)); + if (param == NULL) { + BTC_TRACE_ERROR("handle_rc_attributes_rsp ENOMEM"); + return; + } for (int i = 0; i < attr_count; i++) { if (vendor_msg->vendor_len < attr_index + 8) { - return; + goto error; } - attr_length = (int) vendor_msg->p_vendor_data[7 + attr_index] | vendor_msg->p_vendor_data[6 + attr_index] << 8; + attr_length = (int)(((uint16_t)vendor_msg->p_vendor_data[7 + attr_index]) | + ((uint16_t)vendor_msg->p_vendor_data[6 + attr_index] << 8)); if (vendor_msg->vendor_len < attr_index + attr_length + 8) { - return; + goto error; } //Received attribute text is not null terminated, so it's useful to know it's length param[i].meta_rsp.attr_length = attr_length; param[i].meta_rsp.attr_text = &vendor_msg->p_vendor_data[8 + attr_index]; - attr_id = vendor_msg->p_vendor_data[3 + attr_index] | - vendor_msg->p_vendor_data[2 + attr_index] << 8 | vendor_msg->p_vendor_data[1 + attr_index] << 16 | - vendor_msg->p_vendor_data[attr_index] << 24; + attr_id = ((uint32_t)vendor_msg->p_vendor_data[3 + attr_index]) | + ((uint32_t)vendor_msg->p_vendor_data[2 + attr_index] << 8) | + ((uint32_t)vendor_msg->p_vendor_data[1 + attr_index] << 16) | + ((uint32_t)vendor_msg->p_vendor_data[attr_index] << 24); //Convert to mask id param[i].meta_rsp.attr_id = (1 << (attr_id - 1)); @@ -626,6 +647,9 @@ static void handle_rc_attributes_rsp (tAVRC_MSG_VENDOR *vendor_msg) attr_index += attr_length + 8; } + +error: + osi_free(param); } static void handle_rc_notification_rsp (tAVRC_MSG_VENDOR *vendor_msg) @@ -850,7 +874,7 @@ static void btc_rc_upstreams_evt(UINT16 event, tAVRC_COMMAND *pavrc_cmd, UINT8 c break; case AVRC_PDU_REGISTER_NOTIFICATION: { UINT8 event_id = pavrc_cmd->reg_notif.event_id; - if (event_id > MAX_RC_NOTIFICATIONS) { + if (event_id == 0 || event_id > MAX_RC_NOTIFICATIONS) { BTC_TRACE_WARNING("Invalid event_id: 0x%x", event_id); break; } @@ -889,7 +913,20 @@ static void handle_rc_metamsg_rsp (tBTA_AV_META_MSG *p_meta_msg) { tAVRC_RESPONSE avrc_response = {0}; tAVRC_STS status; - tAVRC_MSG_VENDOR *vendor_msg = &p_meta_msg->p_msg->vendor; + tAVRC_MSG_VENDOR *vendor_msg; + + if (p_meta_msg == NULL || p_meta_msg->p_msg == NULL) { + BTC_TRACE_WARNING("handle_rc_metamsg_rsp: EINVAL p_meta_msg"); + return; + } + + vendor_msg = &p_meta_msg->p_msg->vendor; + if (vendor_msg->p_vendor_data == NULL || + vendor_msg->vendor_len <= AVRC_RSP_OPCODE_OFFSET) { + BTC_TRACE_WARNING("handle_rc_metamsg_rsp: EINVAL vendor_data (%u)", vendor_msg->vendor_len); + return; + } + BTC_TRACE_DEBUG("%s: opcode %d, pdu 0x%x, code %d", __FUNCTION__, p_meta_msg->p_msg->hdr.opcode, vendor_msg->p_vendor_data[AVRC_RSP_OPCODE_OFFSET], p_meta_msg->code); if ( p_meta_msg->p_msg->hdr.opcode != AVRC_OP_VENDOR) { @@ -1491,6 +1528,9 @@ static void btc_avrc_ct_cover_art_get_image_properties(UINT8 *image_handle) static void btc_avrc_ct_cover_art_get_image(UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len) { + if (image_descriptor == NULL || image_descriptor_len == 0) { + return; + } if (btc_rc_cb.rc_cover_art_connected) { BTA_AvCaGet(btc_rc_cb.rc_handle, BTA_AV_CA_GET_IMAGE, image_handle, image_descriptor, image_descriptor_len); } @@ -1618,6 +1658,11 @@ static void btc_avrc_tg_send_rn_rsp(esp_avrc_rn_event_ids_t event_id, esp_avrc_r return; } + if (event_id == 0 || event_id > MAX_RC_NOTIFICATIONS) { + BTC_TRACE_ERROR("btc_avrc_tg_send_rn_rsp: EINVAL evt_id 0x%x", event_id); + return; + } + if (btc_rc_cb.rc_ntf[event_id - 1].registered == FALSE) { BTC_TRACE_ERROR("Event id not registered: event_id = %x", event_id); return; diff --git a/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h b/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h index c44a5e48cc..857c893121 100644 --- a/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h +++ b/components/bt/host/bluedroid/btc/profile/std/include/btc_avrc.h @@ -151,7 +151,7 @@ typedef enum { BTC_TRACE_DEBUG("## %s ##", __FUNCTION__); \ if (btc_rc_cb.rc_connected == FALSE) { \ BTC_TRACE_WARNING("Function %s() called when RC is not connected", __FUNCTION__); \ - return ESP_ERR_INVALID_STATE; \ + return BT_STATUS_FAIL; \ } \ } while (0) diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_api.c b/components/bt/host/bluedroid/stack/avrc/avrc_api.c index 8f9646408f..004613b350 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_api.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_api.c @@ -79,6 +79,10 @@ static void avrc_ctrl_cback(UINT8 handle, UINT8 event, UINT16 result, { UINT8 avrc_event; + if (handle >= AVCT_NUM_CONN) { + return; + } + if (event <= AVRC_MAX_RCV_CTRL_EVT && avrc_cb.ccb[handle].p_ctrl_cback) { avrc_event = avrc_ctrl_event_map[event]; if (event == AVCT_CONNECT_CFM_EVT) { @@ -151,6 +155,10 @@ static void avrc_prep_end_frag(UINT8 handle) UINT8 *p_data, *p_orig_data; UINT8 rsp_type; + if (handle >= AVCT_NUM_CONN) { + return; + } + AVRC_TRACE_DEBUG ("avrc_prep_end_frag" ); p_fcb = &avrc_cb.fcb[handle]; @@ -192,9 +200,17 @@ static void avrc_send_continue_frag(UINT8 handle, UINT8 label) UINT8 cr = AVCT_RSP; tAVRC_RSP rej_rsp; + if (handle >= AVCT_NUM_CONN) { + return; + } + p_fcb = &avrc_cb.fcb[handle]; p_pkt = p_fcb->p_fmsg; + if (p_pkt == NULL) { + return; + } + AVRC_TRACE_DEBUG("%s handle = %u label = %u len = %d", __func__, handle, label, p_pkt->len); if (p_pkt->len > AVRC_MAX_CTRL_DATA_LEN) { @@ -262,6 +278,10 @@ static BT_HDR *avrc_proc_vendor_command(UINT8 handle, UINT8 label, tAVRC_STS status = AVRC_STS_NO_ERROR; tAVRC_FRAG_CB *p_fcb; + if (handle >= AVCT_NUM_CONN) { + return NULL; + } + p_begin = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_begin + AVRC_VENDOR_HDR_SIZE; pkt_type = *(p_data + 1) & AVRC_PKT_TYPE_MASK; @@ -365,6 +385,10 @@ static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_ tAVRC_RASM_CB *p_rcb; tAVRC_NEXT_CMD avrc_cmd; + if (handle >= AVCT_NUM_CONN) { + return 0; + } + p_data = (UINT8 *)(p_pkt + 1) + p_pkt->offset; /* Skip over vendor header (ctype, subunit*, opcode, CO_ID) */ @@ -390,14 +414,22 @@ static UINT8 avrc_proc_far_msg(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR **pp_ /* Allocate buffer for re-assembly */ p_rcb->rasm_pdu = *p_data; if ((p_rcb->p_rmsg = (BT_HDR *)osi_malloc(BT_DEFAULT_BUFFER_SIZE)) != NULL) { + UINT16 buf_payload_max = (UINT16)(BT_DEFAULT_BUFFER_SIZE - sizeof(BT_HDR)); + UINT16 copy_len = p_pkt->len; + if (copy_len > buf_payload_max) { + AVRC_TRACE_WARNING("copy_len(%u) > buf_payload_max(%u)", + (unsigned)copy_len, (unsigned)buf_payload_max); + copy_len = buf_payload_max; + } /* Copy START packet to buffer for re-assembling fragments*/ memcpy(p_rcb->p_rmsg, p_pkt, sizeof(BT_HDR)); /* Copy bt hdr */ /* Copy metadata message */ memcpy((UINT8 *)(p_rcb->p_rmsg + 1), - (UINT8 *)(p_pkt + 1) + p_pkt->offset, p_pkt->len); + (UINT8 *)(p_pkt + 1) + p_pkt->offset, copy_len); /* offset of start of metadata response in reassembly buffer */ + p_rcb->p_rmsg->len = copy_len; p_rcb->p_rmsg->offset = p_rcb->rasm_offset = 0; /* Free original START packet, replace with pointer to reassembly buffer */ @@ -525,6 +557,11 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr, #endif tAVRC_MSG_VENDOR *p_msg = &msg.vendor; + if (handle >= AVCT_NUM_CONN) { + osi_free(p_pkt); + return; + } + if (cr == AVCT_CMD && (p_pkt->layer_specific & AVCT_DATA_CTRL && AVRC_PACKET_LEN < p_pkt->len)) { /* Ignore the invalid AV/C command frame */ @@ -577,6 +614,10 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr, if (cr == AVCT_CMD) { /* send the response to the peer */ p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_UNIT_INFO_RSP_LEN); + if (p_rsp == NULL) { + drop = TRUE; + break; + } p_rsp_data = avrc_get_data_ptr(p_rsp); *p_rsp_data = AVRC_RSP_IMPL_STBL; /* check & set the offset. set response code, set subunit_type & subunit_id, @@ -614,6 +655,10 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr, if (cr == AVCT_CMD) { /* send the response to the peer */ p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_SUB_UNIT_INFO_RSP_LEN); + if (p_rsp == NULL) { + drop = TRUE; + break; + } p_rsp_data = avrc_get_data_ptr(p_rsp); *p_rsp_data = AVRC_RSP_IMPL_STBL; /* check & set the offset. set response code, set (subunit_type & subunit_id), @@ -756,13 +801,17 @@ static void avrc_msg_cback(UINT8 handle, UINT8 label, UINT8 cr, if (reject) { /* reject unsupported opcode */ p_rsp = avrc_copy_packet(p_pkt, AVRC_OP_REJ_MSG_LEN); - p_rsp_data = avrc_get_data_ptr(p_rsp); - *p_rsp_data = AVRC_RSP_REJ; + if (p_rsp == NULL) { + drop = TRUE; + } else { + p_rsp_data = avrc_get_data_ptr(p_rsp); + *p_rsp_data = AVRC_RSP_REJ; #if (BT_USE_TRACES == TRUE) - p_drop_msg = "rejected"; + p_drop_msg = "rejected"; #endif - cr = AVCT_RSP; - drop = TRUE; + cr = AVCT_RSP; + drop = TRUE; + } } if (p_rsp) { @@ -970,6 +1019,10 @@ UINT16 AVRC_MsgReq (UINT8 handle, UINT8 label, UINT8 ctype, BT_HDR *p_pkt) return AVRC_BAD_PARAM; } + if (handle >= AVCT_NUM_CONN) { + return AVRC_BAD_HANDLE; + } + AVRC_TRACE_DEBUG("%s handle = %u label = %u ctype = %u len = %d", __func__, handle, label, ctype, p_pkt->len); diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c b/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c index 279313d4c6..4c260cbec3 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_bld_ct.c @@ -188,6 +188,10 @@ static tAVRC_STS avrc_bld_set_player_value_cmd(tAVRC_SET_APP_VALUE_CMD *p_cmd, B { UINT8 *p_data, *p_start; + if (p_cmd->p_vals == NULL) { + return AVRC_STS_BAD_PARAM; + } + /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; /* pdu + rsvd */ @@ -217,6 +221,10 @@ static tAVRC_STS avrc_bld_get_element_attr_cmd (tAVRC_GET_ELEM_ATTRS_CMD *p_cmd, int i; UINT8 *p_data, *p_start; + if (p_cmd->num_attr > AVRC_MAX_ELEM_ATTR_SIZE) { + return AVRC_STS_BAD_PARAM; + } + AVRC_TRACE_API("avrc_bld_get_element_attr_cmd num_attr: %d", p_cmd->num_attr); /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; @@ -284,13 +292,14 @@ tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt) BT_HDR *p_pkt; BOOLEAN alloc = FALSE; - AVRC_TRACE_API("AVRC_BldCommand: pdu=%x status=%x", p_cmd->cmd.pdu, p_cmd->cmd.status); if (!p_cmd || !pp_pkt) { AVRC_TRACE_API("AVRC_BldCommand. Invalid parameters passed. p_cmd=%p, pp_pkt=%p", p_cmd, pp_pkt); return AVRC_STS_BAD_PARAM; } + AVRC_TRACE_API("AVRC_BldCommand: pdu=%x status=%x", p_cmd->cmd.pdu, p_cmd->cmd.status); + if (*pp_pkt == NULL) { if ((*pp_pkt = avrc_bld_init_cmd_buffer(p_cmd)) == NULL) { AVRC_TRACE_API("AVRC_BldCommand: Failed to initialize command buffer"); @@ -333,6 +342,10 @@ tAVRC_STS AVRC_BldCommand( tAVRC_COMMAND *p_cmd, BT_HDR **pp_pkt) case AVRC_PDU_GET_CAPABILITIES: status = avrc_bld_get_caps_cmd(&p_cmd->get_caps, p_pkt); break; + + default: + status = AVRC_STS_BAD_PARAM; + break; } if (alloc && (status != AVRC_STS_NO_ERROR) ) { diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c b/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c index 7962382980..e82a051272 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_bld_tg.c @@ -47,6 +47,7 @@ static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR UINT8 xx; UINT32 *p_company_id; UINT8 *p_event_id; + UINT8 count; tAVRC_STS status = AVRC_STS_NO_ERROR; if (!(AVRC_IS_VALID_CAP_ID(p_rsp->capability_id))) { @@ -64,25 +65,31 @@ static tAVRC_STS avrc_bld_get_capability_rsp (tAVRC_GET_CAPS_RSP *p_rsp, BT_HDR UINT8_TO_BE_STREAM(p_data, p_rsp->capability_id); p_count = p_data; + if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) { + count = (p_rsp->count > AVRC_CAP_MAX_NUM_COMP_ID) ? AVRC_CAP_MAX_NUM_COMP_ID : p_rsp->count; + } else { + count = (p_rsp->count > AVRC_CAP_MAX_NUM_EVT_ID) ? AVRC_CAP_MAX_NUM_EVT_ID : p_rsp->count; + } + if (len == 0) { - *p_count = p_rsp->count; + *p_count = count; p_data++; len = 2; /* move past the capability_id and count */ } else { p_data = p_start + p_pkt->len; - *p_count += p_rsp->count; + *p_count += count; } if (p_rsp->capability_id == AVRC_CAP_COMPANY_ID) { p_company_id = p_rsp->param.company_id; - for (xx = 0; xx < p_rsp->count; xx++) { + for (xx = 0; xx < count; xx++) { UINT24_TO_BE_STREAM(p_data, p_company_id[xx]); } - len += p_rsp->count * 3; + len += count * 3; } else { p_event_id = p_rsp->param.event_id; *p_count = 0; - for (xx = 0; xx < p_rsp->count; xx++) { + for (xx = 0; xx < count; xx++) { if (AVRC_IS_VALID_EVENT_ID(p_event_id[xx])) { (*p_count)++; UINT8_TO_BE_STREAM(p_data, p_event_id[xx]); @@ -113,6 +120,12 @@ static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p UINT8 *p_data, *p_start, *p_len, *p_num; UINT16 len = 0; UINT8 xx; + UINT8 num_attr; + + num_attr = p_rsp->num_attr; + if (num_attr > AVRC_MAX_APP_ATTR_SIZE) { + num_attr = AVRC_MAX_APP_ATTR_SIZE; + } AVRC_TRACE_API("avrc_bld_list_app_settings_attr_rsp"); /* get the existing length, if any, and also the num attributes */ @@ -129,7 +142,7 @@ static tAVRC_STS avrc_bld_list_app_settings_attr_rsp (tAVRC_LIST_APP_ATTR_RSP *p p_data = p_start + p_pkt->len; } - for (xx = 0; xx < p_rsp->num_attr; xx++) { + for (xx = 0; xx < num_attr; xx++) { if (AVRC_IsValidPlayerAttr(p_rsp->attrs[xx])) { (*p_num)++; UINT8_TO_BE_STREAM(p_data, p_rsp->attrs[xx]); @@ -160,6 +173,12 @@ static tAVRC_STS avrc_bld_list_app_settings_values_rsp (tAVRC_LIST_APP_VALUES_RS UINT8 *p_data, *p_start, *p_len, *p_num; UINT8 xx; UINT16 len; + UINT8 num_val; + + num_val = p_rsp->num_val; + if (num_val > AVRC_MAX_APP_ATTR_SIZE) { + num_val = AVRC_MAX_APP_ATTR_SIZE; + } AVRC_TRACE_API("avrc_bld_list_app_settings_values_rsp"); @@ -171,15 +190,15 @@ static tAVRC_STS avrc_bld_list_app_settings_values_rsp (tAVRC_LIST_APP_VALUES_RS p_num = p_data; /* first time initialize the attribute count */ if (len == 0) { - *p_num = p_rsp->num_val; + *p_num = num_val; p_data++; } else { p_data = p_start + p_pkt->len; - *p_num += p_rsp->num_val; + *p_num += num_val; } - for (xx = 0; xx < p_rsp->num_val; xx++) { + for (xx = 0; xx < num_val; xx++) { UINT8_TO_BE_STREAM(p_data, p_rsp->vals[xx]); } @@ -206,6 +225,7 @@ static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len; UINT8 xx; + UINT8 num_val; if (!p_rsp->p_vals) { AVRC_TRACE_ERROR("avrc_bld_get_cur_app_setting_value_rsp NULL parameter"); @@ -227,7 +247,12 @@ static tAVRC_STS avrc_bld_get_cur_app_setting_value_rsp (tAVRC_GET_CUR_APP_VALUE p_data = p_start + p_pkt->len; } - for (xx = 0; xx < p_rsp->num_val; xx++) { + num_val = p_rsp->num_val; + if (num_val > AVRC_MAX_APP_ATTR_SIZE) { + num_val = AVRC_MAX_APP_ATTR_SIZE; + } + + for (xx = 0; xx < num_val; xx++) { if (avrc_is_valid_player_attrib_value(p_rsp->p_vals[xx].attr_id, p_rsp->p_vals[xx].attr_val)) { (*p_count)++; UINT8_TO_BE_STREAM(p_data, p_rsp->p_vals[xx].attr_id); @@ -424,7 +449,11 @@ static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, B { UINT8 *p_data, *p_start, *p_len, *p_count; UINT16 len; + UINT16 len_left; UINT8 xx; + UINT8 num_attr; + UINT16 str_len; + tAVRC_STS sts = AVRC_STS_NO_ERROR; AVRC_TRACE_API("avrc_bld_get_elem_attrs_rsp"); if (!p_rsp->p_attrs) { @@ -432,6 +461,11 @@ static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, B return AVRC_STS_BAD_PARAM; } + num_attr = p_rsp->num_attr; + if (num_attr > AVRC_MAX_ELEM_ATTR_SIZE) { + num_attr = AVRC_MAX_ELEM_ATTR_SIZE; + } + /* get the existing length, if any, and also the num attributes */ p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_len = p_start + 2; /* pdu + rsvd */ @@ -446,24 +480,37 @@ static tAVRC_STS avrc_bld_get_elem_attrs_rsp (tAVRC_GET_ELEM_ATTRS_RSP *p_rsp, B p_data = p_start + p_pkt->len; } - for (xx = 0; xx < p_rsp->num_attr; xx++) { + for (xx = 0; xx < num_attr; xx++) { if (!AVRC_IS_VALID_MEDIA_ATTRIBUTE(p_rsp->p_attrs[xx].attr_id)) { AVRC_TRACE_ERROR("avrc_bld_get_elem_attrs_rsp invalid attr id[%d]: %d", xx, p_rsp->p_attrs[xx].attr_id); continue; } - if ( !p_rsp->p_attrs[xx].name.p_str ) { - p_rsp->p_attrs[xx].name.str_len = 0; + str_len = p_rsp->p_attrs[xx].name.str_len; + if (str_len > 0 && p_rsp->p_attrs[xx].name.p_str == NULL) { + sts = AVRC_STS_BAD_PARAM; + break; + } + len_left = (UINT16)(((UINT8 *)p_pkt + BT_DEFAULT_BUFFER_SIZE) - p_data); + if (len_left < 8 || (UINT32)str_len > (UINT32)len_left - 8) { + sts = AVRC_STS_INTERNAL_ERR; + break; } UINT32_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].attr_id); UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.charset_id); - UINT16_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.str_len); - ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, p_rsp->p_attrs[xx].name.str_len); + UINT16_TO_BE_STREAM(p_data, str_len); + if (str_len > 0) { + ARRAY_TO_BE_STREAM(p_data, p_rsp->p_attrs[xx].name.p_str, str_len); + } (*p_count)++; } - len = p_data - p_count; - UINT16_TO_BE_STREAM(p_len, len); - p_pkt->len = (p_data - p_start); - return AVRC_STS_NO_ERROR; + + if (sts == AVRC_STS_NO_ERROR) { + len = p_data - p_count; + UINT16_TO_BE_STREAM(p_len, len); + p_pkt->len = (p_data - p_start); + } + + return sts; } /******************************************************************************* @@ -485,7 +532,7 @@ static tAVRC_STS avrc_bld_get_play_status_rsp (tAVRC_GET_PLAY_STATUS_RSP *p_rsp, p_start = (UINT8 *)(p_pkt + 1) + p_pkt->offset; p_data = p_start + 2; - /* add fixed lenth - song len(4) + song position(4) + status(1) */ + /* add fixed length - song len(4) + song position(4) + status(1) */ UINT16_TO_BE_STREAM(p_data, 9); UINT32_TO_BE_STREAM(p_data, p_rsp->song_len); UINT32_TO_BE_STREAM(p_data, p_rsp->song_pos); @@ -582,7 +629,6 @@ static tAVRC_STS avrc_bld_notify_rsp (tAVRC_REG_NOTIF_RSP *p_rsp, BT_HDR *p_pkt) UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_id[xx]); UINT8_TO_BE_STREAM(p_data, p_rsp->param.player_setting.attr_value[xx]); } else { - AVRC_TRACE_ERROR("bad player app seeting attribute or value"); status = AVRC_STS_BAD_PARAM; break; } @@ -740,6 +786,9 @@ static BT_HDR *avrc_bld_init_rsp_buffer(tAVRC_RESPONSE *p_rsp) case AVRC_OP_VENDOR: offset = AVRC_MSG_VENDOR_OFFSET; break; + + default: + return NULL; } /* allocate and initialize the buffer */ @@ -763,7 +812,7 @@ static BT_HDR *avrc_bld_init_rsp_buffer(tAVRC_RESPONSE *p_rsp) /* reserved 0, packet_type 0 */ UINT8_TO_BE_STREAM(p_data, 0); /* continue to the next "case to add length */ - /* add fixed lenth - 0 */ + /* add fixed length - 0 */ UINT16_TO_BE_STREAM(p_data, 0); break; } diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_opt.c b/components/bt/host/bluedroid/stack/avrc/avrc_opt.c index cd933df73e..ff3a26870f 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_opt.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_opt.c @@ -65,11 +65,11 @@ static BT_HDR *avrc_vendor_msg(tAVRC_MSG_VENDOR *p_msg) } #if AVRC_METADATA_INCLUDED == TRUE - if ((AVRC_META_CMD_BUF_SIZE > AVRC_MIN_VENDOR_CMD_LEN + p_msg->vendor_len) && + if ((AVRC_META_CMD_BUF_SIZE >= AVRC_MIN_VENDOR_CMD_LEN + p_msg->vendor_len) && ((p_cmd = (BT_HDR *) osi_malloc(AVRC_META_CMD_BUF_SIZE)) != NULL)) #else - if ((AVRC_CMD_BUF_SIZE > (AVRC_MIN_VENDOR_CMD_LEN + p_msg->vendor_len)) && - (p_cmd = (BT_HDR *) osi_malloc(AVRC_CMD_BUF_SIZE)) != NULL) + if ((AVRC_CMD_BUF_SIZE >= (AVRC_MIN_VENDOR_CMD_LEN + p_msg->vendor_len)) && + ((p_cmd = (BT_HDR *) osi_malloc(AVRC_CMD_BUF_SIZE)) != NULL)) #endif { p_cmd->offset = AVCT_MSG_OFFSET; @@ -80,6 +80,9 @@ static BT_HDR *avrc_vendor_msg(tAVRC_MSG_VENDOR *p_msg) AVRC_CO_ID_TO_BE_STREAM(p_data, p_msg->company_id); if (p_msg->vendor_len && p_msg->p_vendor_data) { memcpy(p_data, p_msg->p_vendor_data, p_msg->vendor_len); + } else if (p_msg->vendor_len && p_msg->p_vendor_data == NULL) { + osi_free(p_cmd); + return NULL; } p_cmd->len = (UINT16) (p_data + p_msg->vendor_len - (UINT8 *)(p_cmd + 1) - p_cmd->offset); p_cmd->layer_specific = AVCT_DATA_CTRL; diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c b/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c index 80874aa397..26b8d3147e 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_pars_ct.c @@ -103,7 +103,7 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p BE_STREAM_TO_UINT8 (eventid, p); if (AVRC_EVT_VOLUME_CHANGE == eventid && (AVRC_RSP_CHANGED == p_msg->hdr.ctype || AVRC_RSP_INTERIM == p_msg->hdr.ctype - || AVRC_RSP_REJ == p_msg->hdr.ctype || AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) { + || AVRC_RSP_NOT_IMPL == p_msg->hdr.ctype)) { if (len < 2) { AVRC_TRACE_WARNING("invalid message length %u: must be at least 2", len); return AVRC_STS_INTERNAL_ERR; @@ -114,8 +114,8 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p } // todo: parse the response for other event_ids AVRC_TRACE_DEBUG("avrc_pars_vendor_rsp PDU reg notif response:event 0x%x", eventid); - break; #endif /* (AVRC_ADV_CTRL_INCLUDED == TRUE) */ + break; case AVRC_PDU_GET_CAPABILITIES: /* 0x10 */ if (len < 2) { AVRC_TRACE_WARNING("invalid message length %u: must be at least 2", len); @@ -137,8 +137,7 @@ static tAVRC_STS avrc_pars_vendor_rsp(tAVRC_MSG_VENDOR *p_msg, tAVRC_RESPONSE *p if (p_result->get_caps.count > AVRC_CAP_MAX_NUM_COMP_ID) { status = AVRC_STS_INTERNAL_ERR; } else { - if (len < 2 + p_result->get_caps.count * 6) { - AVRC_TRACE_WARNING("invalid message length %u: must be at least %d", len, 2 + p_result->get_caps.count * 6); + if (len < 2 + p_result->get_caps.count * 3) { return AVRC_STS_INTERNAL_ERR; } for (int i = 0; i < p_result->get_caps.count; ++i) { diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c b/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c index 755c5ae1d3..840f4c9855 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c @@ -50,7 +50,6 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ UINT16 *p_u16; UINT32 u32, u32_2, *p_u32; tAVRC_APP_SETTING *p_app_set; - UINT16 size_needed; /* Check the vendor data */ if (p_msg->vendor_len == 0) { @@ -114,6 +113,10 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ status = AVRC_STS_INTERNAL_ERR; } else { BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p); + if (p_result->get_cur_app_val.num_attr > AVRC_MAX_APP_ATTR_SIZE) { + status = AVRC_STS_INTERNAL_ERR; + break; + } if (len != (p_result->get_cur_app_val.num_attr + 1)) { status = AVRC_STS_INTERNAL_ERR; break; @@ -122,7 +125,9 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ for (xx = 0, yy = 0; xx < p_result->get_cur_app_val.num_attr; xx++) { /* only report the valid player app attributes */ if (AVRC_IsValidPlayerAttr(*p)) { - p_u8[yy++] = *p; + if (yy < AVRC_MAX_APP_ATTR_SIZE) { + p_u8[yy++] = *p; + } } p++; } @@ -138,11 +143,13 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ status = AVRC_STS_INTERNAL_ERR; } else { BE_STREAM_TO_UINT8 (p_result->set_app_val.num_val, p); - size_needed = sizeof(tAVRC_APP_SETTING); if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) { p_result->set_app_val.p_vals = (tAVRC_APP_SETTING *)p_buf; p_app_set = p_result->set_app_val.p_vals; - for (xx = 0; ((xx < p_result->set_app_val.num_val) && (buf_len > size_needed)); xx++) { + for (xx = 0; xx < p_result->set_app_val.num_val; xx++) { + if (buf_len < (UINT16)((xx + 1) * sizeof(tAVRC_APP_SETTING))) { + break; + } p_app_set[xx].attr_id = *p++; p_app_set[xx].attr_val = *p++; if (!avrc_is_valid_player_attrib_value(p_app_set[xx].attr_id, p_app_set[xx].attr_val)) { @@ -170,7 +177,9 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ status = AVRC_STS_BAD_PARAM; } else { BE_STREAM_TO_UINT8 (p_result->get_app_val_txt.num_val, p); - if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val) { + if (p_result->get_app_val_txt.num_val > AVRC_MAX_APP_ATTR_SIZE) { + status = AVRC_STS_INTERNAL_ERR; + } else if ( (len - 2/* attr_id & num_val */) != p_result->get_app_val_txt.num_val) { status = AVRC_STS_INTERNAL_ERR; } else { p_u8 = p_result->get_app_val_txt.vals; @@ -192,13 +201,12 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ status = AVRC_STS_INTERNAL_ERR; } else { BE_STREAM_TO_UINT8 (p_result->inform_charset.num_id, p); - if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2) { + if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE) { + status = AVRC_STS_INTERNAL_ERR; + } else if ( (len - 1/* num_id */) != p_result->inform_charset.num_id * 2) { status = AVRC_STS_INTERNAL_ERR; } else { p_u16 = p_result->inform_charset.charsets; - if (p_result->inform_charset.num_id > AVRC_MAX_CHARSET_SIZE) { - p_result->inform_charset.num_id = AVRC_MAX_CHARSET_SIZE; - } for (xx = 0; xx < p_result->inform_charset.num_id; xx++) { BE_STREAM_TO_UINT16 (p_u16[xx], p); } @@ -225,13 +233,12 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ BE_STREAM_TO_UINT32 (u32_2, p); if (u32 == 0 && u32_2 == 0) { BE_STREAM_TO_UINT8 (p_result->get_elem_attrs.num_attr, p); - if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4)) { + if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE) { + status = AVRC_STS_INTERNAL_ERR; + } else if ( (len - 9/* UID/8 and num_attr/1 */) != (p_result->get_elem_attrs.num_attr * 4)) { status = AVRC_STS_INTERNAL_ERR; } else { p_u32 = p_result->get_elem_attrs.attrs; - if (p_result->get_elem_attrs.num_attr > AVRC_MAX_ELEM_ATTR_SIZE) { - p_result->get_elem_attrs.num_attr = AVRC_MAX_ELEM_ATTR_SIZE; - } for (xx = 0; xx < p_result->get_elem_attrs.num_attr; xx++) { BE_STREAM_TO_UINT32 (p_u32[xx], p); } diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c b/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c index 3d84d1f985..5eb3e0031b 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_sdp.c @@ -110,7 +110,9 @@ static void avrc_sdp_cback(UINT16 status) avrc_cb.service_uuid = 0; /* return info from sdp record in app callback function */ - (*avrc_cb.p_cback) (status); + if (avrc_cb.p_cback != NULL) { + (*avrc_cb.p_cback) (status); + } return; } diff --git a/components/bt/host/bluedroid/stack/avrc/avrc_utils.c b/components/bt/host/bluedroid/stack/avrc/avrc_utils.c index addb1b68e5..8dd4cdfe72 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_utils.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_utils.c @@ -171,7 +171,8 @@ tAVRC_STS avrc_pars_pass_thru(tAVRC_MSG_PASS *p_msg, UINT16 *p_vendor_unique_id) UINT16 id; tAVRC_STS status = AVRC_STS_BAD_CMD; - if (p_msg->op_id == AVRC_ID_VENDOR && p_msg->pass_len == AVRC_PASS_THRU_GROUP_LEN) { + if (p_msg && p_msg->p_pass_data && p_msg->op_id == AVRC_ID_VENDOR && + p_msg->pass_len == AVRC_PASS_THRU_GROUP_LEN) { p_data = p_msg->p_pass_data; AVRC_BE_STREAM_TO_CO_ID (co_id, p_data); if (co_id == AVRC_CO_METADATA) { diff --git a/components/bt/host/bluedroid/stack/include/stack/sdp_api.h b/components/bt/host/bluedroid/stack/include/stack/sdp_api.h index 7075e8bbf3..baf15b2995 100644 --- a/components/bt/host/bluedroid/stack/include/stack/sdp_api.h +++ b/components/bt/host/bluedroid/stack/include/stack/sdp_api.h @@ -180,15 +180,16 @@ extern "C" ** Function SDP_InitDiscoveryDb ** ** Description This function is called to initialize a discovery database. +** It will no longer use p_attr_list and p_uuid_list after calling it. ** ** Returns TRUE if successful, FALSE if one or more parameters are bad ** *******************************************************************************/ extern BOOLEAN SDP_InitDiscoveryDb (tSDP_DISCOVERY_DB *p_db, UINT32 len, UINT16 num_uuid, - tSDP_UUID *p_uuid_list, + const tSDP_UUID *p_uuid_list, UINT16 num_attr, - UINT16 *p_attr_list); + const UINT16 *p_attr_list); /******************************************************************************* ** diff --git a/components/bt/host/bluedroid/stack/sdp/sdp_api.c b/components/bt/host/bluedroid/stack/sdp/sdp_api.c index 9b477a1c85..1321c4108a 100644 --- a/components/bt/host/bluedroid/stack/sdp/sdp_api.c +++ b/components/bt/host/bluedroid/stack/sdp/sdp_api.c @@ -46,6 +46,7 @@ ** Function SDP_InitDiscoveryDb ** ** Description This function is called to initialize a discovery database. +** It will no longer use p_attr_list and p_uuid_list after calling it. ** ** Parameters: p_db - (input) address of an area of memory where the ** discovery database is managed. @@ -63,7 +64,7 @@ ** *******************************************************************************/ BOOLEAN SDP_InitDiscoveryDb (tSDP_DISCOVERY_DB *p_db, UINT32 len, UINT16 num_uuid, - tSDP_UUID *p_uuid_list, UINT16 num_attr, UINT16 *p_attr_list) + const tSDP_UUID *p_uuid_list, UINT16 num_attr, const UINT16 *p_attr_list) { #if SDP_CLIENT_ENABLED == TRUE UINT16 xx;