diff --git a/components/bt/host/bluedroid/api/esp_a2dp_api.c b/components/bt/host/bluedroid/api/esp_a2dp_api.c index 99033b0b857..55c534e9caa 100644 --- a/components/bt/host/bluedroid/api/esp_a2dp_api.c +++ b/components/bt/host/bluedroid/api/esp_a2dp_api.c @@ -125,6 +125,7 @@ esp_err_t esp_a2d_sink_disconnect(esp_bd_addr_t remote_bda) msg.pid = BTC_PID_A2DP; msg.act = BTC_AV_SINK_API_DISCONNECT_EVT; + memset(&arg, 0, sizeof(btc_av_args_t)); /* Switch to BTC context */ memcpy(&(arg.disconn), remote_bda, sizeof(bt_bdaddr_t)); stat = btc_transfer_context(&msg, &arg, sizeof(btc_av_args_t), NULL, NULL); @@ -213,6 +214,10 @@ esp_err_t esp_a2d_media_ctrl(esp_a2d_media_ctrl_t ctrl) ctrl = ESP_A2D_MEDIA_CTRL_SUSPEND; } + if (ctrl <= ESP_A2D_MEDIA_CTRL_NONE || ctrl > ESP_A2D_MEDIA_CTRL_SUSPEND) { + return ESP_ERR_INVALID_ARG; + } + bt_status_t stat; btc_av_args_t arg; btc_msg_t msg; diff --git a/components/bt/host/bluedroid/bta/ar/bta_ar.c b/components/bt/host/bluedroid/bta/ar/bta_ar.c index cd70eeec240..f1b270036cc 100644 --- a/components/bt/host/bluedroid/bta/ar/bta_ar.c +++ b/components/bt/host/bluedroid/bta/ar/bta_ar.c @@ -146,10 +146,11 @@ void bta_ar_dereg_avdt(tBTA_SYS_ID sys_id) bta_ar_cb.p_avk_conn_cback = NULL; mask = BTA_AR_AVK_MASK; } - bta_ar_cb.avdt_registered &= ~mask; - - if (bta_ar_cb.avdt_registered == 0) { - AVDT_Deregister(); + if (mask) { + bta_ar_cb.avdt_registered &= ~mask; + if (bta_ar_cb.avdt_registered == 0) { + AVDT_Deregister(); + } } } @@ -170,6 +171,7 @@ void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, BD_ADDR bd_addr) UINT8 event = BTA_AR_AVDT_CONN_EVT; tAVDT_CTRL data; + memset(&data, 0, sizeof(tAVDT_CTRL)); if (sys_id == BTA_ID_AV) { if (bta_ar_cb.p_avk_conn_cback) { (*bta_ar_cb.p_avk_conn_cback)(0, bd_addr, event, &data); @@ -215,10 +217,11 @@ void bta_ar_dereg_avct(tBTA_SYS_ID sys_id) { UINT8 mask = bta_ar_id (sys_id); - bta_ar_cb.avct_registered &= ~mask; - - if (bta_ar_cb.avct_registered == 0) { - AVCT_Deregister(); + if (mask) { + bta_ar_cb.avct_registered &= ~mask; + if (bta_ar_cb.avct_registered == 0) { + AVCT_Deregister(); + } } } @@ -299,12 +302,12 @@ void bta_ar_dereg_avrc(UINT16 service_uuid, tBTA_SYS_ID sys_id) bta_ar_cb.ct_categories [mask - 1] = 0; categories = bta_ar_cb.ct_categories[0] | bta_ar_cb.ct_categories[1]; if (!categories) { - /* no CT is still registered - cleaup */ + /* no CT is still registered - cleanup */ SDP_DeleteRecord(bta_ar_cb.sdp_ct_handle); bta_ar_cb.sdp_ct_handle = 0; bta_sys_remove_uuid(service_uuid); } else { - /* change supported categories to the remaning one */ + /* change supported categories to the remaining one */ p = temp; UINT16_TO_BE_STREAM(p, categories); SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, diff --git a/components/bt/host/bluedroid/bta/av/bta_av_aact.c b/components/bt/host/bluedroid/bta/av/bta_av_aact.c index 2ff0815c074..c2511bba3c7 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_aact.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_aact.c @@ -522,6 +522,11 @@ static void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, t } /* look up application event */ + /* bounds check to avoid out-of-bounds read */ + if (event >= sizeof(bta_av_stream_evt_ok) / sizeof(bta_av_stream_evt_ok[0])) { + osi_free(p_msg); + return; + } if ((p_data == NULL) || (p_data->hdr.err_code == 0)) { p_msg->hdr.event = bta_av_stream_evt_ok[event]; if (p_msg->hdr.event == BTA_AV_STR_START_OK_EVT) { @@ -582,7 +587,7 @@ void bta_av_stream_data_cback(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UI /* Get SCB and correct sep type*/ for (index = 0; index < BTA_AV_NUM_STRS; index ++ ) { p_scb = bta_av_cb.p_scb[index]; - if ((p_scb->avdt_handle == handle) && (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK)) { + if (p_scb && (p_scb->avdt_handle == handle) && (p_scb->seps[p_scb->sep_idx].tsep == AVDT_TSEP_SNK)) { break; } } @@ -722,6 +727,7 @@ static void bta_av_a2d_sdp_cback(BOOLEAN found, tA2D_Service *p_service) bta_sys_sendmsg(p_msg); } else { APPL_TRACE_ERROR ("bta_av_a2d_sdp_cback, no scb found for handle(0x%x)", bta_av_cb.handle); + osi_free(p_msg); } } } @@ -1633,7 +1639,7 @@ void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) p_data->str_msg.msg.discover_cfm.p_sep_info[i].tsep ); } - for (i = 0; i < p_scb->num_seps; i++) { + for (i = 0; i < num_seps; i++) { /* steam not in use, is a sink, and is audio */ if ((p_scb->sep_info[i].in_use == FALSE) && (p_scb->sep_info[i].media_type == p_scb->media_type)) { @@ -1873,6 +1879,11 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) UINT16 uuid_int; /* UUID for which connection was initiated */ tBTA_AV_SNK_PSC_CFG psc_cfg = {0}; + if (p_scb->p_cap == NULL) { + APPL_TRACE_ERROR("bta_av_getcap_results: p_cap is NULL"); + bta_av_ssm_execute(p_scb, BTA_AV_STR_GETCAP_FAIL_EVT, p_data); + return; + } memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG)); cfg.num_codec = 1; cfg.num_protect = p_scb->p_cap->num_protect; @@ -2167,9 +2178,9 @@ void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) bta_sys_stop_timer(&p_scb->timer); memcpy(p_cfg, &p_scb->cfg, sizeof(tAVDT_CFG)); - p_cfg->num_protect = p_rcfg->num_protect; + p_cfg->num_protect = (p_rcfg->num_protect <= AVDT_PROTECT_SIZE) ? p_rcfg->num_protect : AVDT_PROTECT_SIZE; memcpy(p_cfg->codec_info, p_rcfg->codec_info, AVDT_CODEC_SIZE); - memcpy(p_cfg->protect_info, p_rcfg->p_protect_info, p_rcfg->num_protect); + memcpy(p_cfg->protect_info, p_rcfg->p_protect_info, p_cfg->num_protect); p_scb->rcfg_idx = p_rcfg->sep_info_idx; p_scb->p_cap->psc_mask = p_scb->cur_psc_mask; @@ -2382,7 +2393,12 @@ void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) * If the code were to be re-arranged for some reasons, this number may need to be changed */ p_scb->co_started = bta_av_cb.audio_open_cnt; - flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1]; + if (p_scb->co_started > 0) { + flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1]; + } else { + APPL_TRACE_ERROR("bta_av_start_ok: co_started is 0"); + flush_to = p_bta_av_cfg->p_audio_flush_to[0]; + } } else { flush_to = p_bta_av_cfg->video_flush_to; } @@ -2774,7 +2790,11 @@ void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) if (AVDT_ERR_CONNECT == err_code) { /* report failure */ evt.status = BTA_AV_FAIL; - (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt); + evt.chnl = p_scb->chnl; + evt.hndl = p_scb->hndl; + if (bta_av_cb.p_cback) { + (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt); + } bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL); } else { APPL_TRACE_ERROR("suspend rejected, try close"); @@ -2790,9 +2810,18 @@ void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) } else { APPL_TRACE_DEBUG("bta_av_suspend_cont calling AVDT_ReconfigReq"); /* reconfig the stream */ - - AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap); - p_scb->p_cap->psc_mask = p_scb->cur_psc_mask; + if (p_scb->p_cap == NULL) { + evt.status = BTA_AV_FAIL; + evt.chnl = p_scb->chnl; + evt.hndl = p_scb->hndl; + if (bta_av_cb.p_cback) { + (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt); + } + bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL); + } else { + AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap); + p_scb->p_cap->psc_mask = p_scb->cur_psc_mask; + } } } diff --git a/components/bt/host/bluedroid/bta/av/bta_av_act.c b/components/bt/host/bluedroid/bta/av/bta_av_act.c index 434dfa8b22e..13d0901e989 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_act.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_act.c @@ -298,12 +298,18 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx) tAVRC_CONN_CB ccb; BD_ADDR_PTR bda = (BD_ADDR_PTR)bd_addr_any; UINT8 status = BTA_AV_RC_ROLE_ACP; - tBTA_AV_SCB *p_scb = p_cb->p_scb[shdl - 1]; + tBTA_AV_SCB *p_scb = NULL; int i; UINT8 rc_handle; tBTA_AV_RCB *p_rcb; + if (shdl > 0 && shdl <= BTA_AV_NUM_STRS) { + p_scb = p_cb->p_scb[shdl - 1]; + } if (role == AVCT_INT) { + if (p_scb == NULL) { + return BTA_AV_RC_HANDLE_NONE; + } bda = p_scb->peer_addr; status = BTA_AV_RC_ROLE_INT; } else { @@ -325,6 +331,11 @@ UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx) return BTA_AV_RC_HANDLE_NONE; } + if (rc_handle >= BTA_AV_NUM_RCB) { + APPL_TRACE_ERROR("bta_av_rc_create: EINVAL rc_handle %u", rc_handle); + AVRC_Close(rc_handle); + return BTA_AV_RC_HANDLE_NONE; + } i = rc_handle; p_rcb = &p_cb->rcb[i]; @@ -834,7 +845,7 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) tBTA_AV av; BT_HDR *p_pkt = NULL; tAVRC_MSG_VENDOR *p_vendor = &p_data->rc_msg.msg.vendor; - BOOLEAN is_inquiry = ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) || p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ); + BOOLEAN is_inquiry = ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) || (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ)); #if (AVRC_METADATA_INCLUDED == TRUE) UINT8 ctype = 0; tAVRC_RESPONSE rc_rsp; @@ -936,7 +947,9 @@ void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data) /* else if not configured to support vendor specific and it's a command */ else if (!(p_cb->features & BTA_AV_FEAT_VENDOR) && p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ) { - if (p_data->rc_msg.msg.vendor.p_vendor_data[0] == AVRC_PDU_INVALID) { + if (p_data->rc_msg.msg.vendor.p_vendor_data != NULL && + p_data->rc_msg.msg.vendor.vendor_len >= 5 && + p_data->rc_msg.msg.vendor.p_vendor_data[0] == AVRC_PDU_INVALID) { /* reject it */ p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ; p_data->rc_msg.msg.vendor.p_vendor_data[4] = AVRC_STS_BAD_CMD; @@ -1704,11 +1717,16 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) /* cannot create valid rc_handle for current device. report failure */ APPL_TRACE_ERROR("%s: no link resources available", __func__); p_scb->use_rc = FALSE; + rc_open.rc_handle = BTA_AV_RC_HANDLE_NONE; bdcpy(rc_open.peer_addr, p_scb->peer_addr); rc_open.peer_features = 0; + rc_open.peer_ct_features = 0; + rc_open.peer_tg_features = 0; rc_open.sdp_disc_done = FALSE; rc_open.status = BTA_AV_FAIL_SDP; - (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open); + if (p_cb->p_cback) { + (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open); + } } } #if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE) @@ -1719,11 +1737,16 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) } else if (p_scb->use_rc) { /* can not find AVRC on peer device. report failure */ p_scb->use_rc = FALSE; + rc_open.rc_handle = BTA_AV_RC_HANDLE_NONE; bdcpy(rc_open.peer_addr, p_scb->peer_addr); rc_open.peer_features = 0; + rc_open.peer_ct_features = 0; + rc_open.peer_tg_features = 0; rc_open.sdp_disc_done = FALSE; rc_open.status = BTA_AV_FAIL_SDP; - (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open); + if (p_cb->p_cback) { + (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open); + } } } } else { @@ -1737,7 +1760,9 @@ void bta_av_rc_disc_done(tBTA_AV_DATA *p_data) rc_feat.peer_features = peer_features; rc_feat.peer_ct_features = peer_ct_features; rc_feat.peer_tg_features = peer_tg_features; - (*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, (tBTA_AV *) &rc_feat); + if (p_cb->p_cback) { + (*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, (tBTA_AV *) &rc_feat); + } } } @@ -1866,12 +1891,17 @@ void bta_av_rc_disc(UINT8 disc) if ((disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK) { /* this is the rc handle/index to tBTA_AV_RCB */ rc_handle = disc & (~BTA_AV_CHNL_MSK); - if (p_cb->rcb[rc_handle].lidx) { + if (rc_handle < BTA_AV_NUM_RCB && p_cb->rcb[rc_handle].lidx > 0 && + p_cb->rcb[rc_handle].lidx <= (BTA_AV_NUM_LINKS + 1)) { p_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr; } } else { - hdi = (disc & BTA_AV_HNDL_MSK) - 1; - p_scb = p_cb->p_scb[hdi]; + hdi = (disc & BTA_AV_HNDL_MSK); + if (hdi > 0 && (hdi - 1) < BTA_AV_NUM_STRS) { + p_scb = p_cb->p_scb[hdi - 1]; + } else { + p_scb = NULL; + } if (p_scb) { APPL_TRACE_DEBUG("rc_handle %d", p_scb->rc_handle); diff --git a/components/bt/host/bluedroid/bta/av/bta_av_api.c b/components/bt/host/bluedroid/bta/av/bta_av_api.c index 673cbe8539b..4e6b4f6d15e 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_api.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_api.c @@ -117,6 +117,7 @@ void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id, p_buf->hdr.event = BTA_AV_API_REGISTER_EVT; if (p_service_name) { BCM_STRNCPY_S(p_buf->p_service_name, p_service_name, BTA_SERVICE_NAME_LEN); + p_buf->p_service_name[BTA_SERVICE_NAME_LEN] = '\0'; } else { p_buf->p_service_name[0] = '\0'; } @@ -327,8 +328,14 @@ void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx, void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len) { tBTA_AV_API_PROTECT_REQ *p_buf; + size_t alloc_size; - if ((p_buf = (tBTA_AV_API_PROTECT_REQ *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_PROTECT_REQ) + len))) != NULL) { + /* Cap allocation size to avoid UINT16 overflow */ + alloc_size = sizeof(tBTA_AV_API_PROTECT_REQ) + len; + if (alloc_size > 0xFFFF) { + return; + } + if ((p_buf = (tBTA_AV_API_PROTECT_REQ *) osi_malloc((UINT16) alloc_size)) != NULL) { p_buf->hdr.layer_specific = hndl; p_buf->hdr.event = BTA_AV_API_PROTECT_REQ_EVT; p_buf->len = len; @@ -357,8 +364,14 @@ void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len) void BTA_AvProtectRsp(tBTA_AV_HNDL hndl, UINT8 error_code, UINT8 *p_data, UINT16 len) { tBTA_AV_API_PROTECT_RSP *p_buf; + size_t alloc_size; - if ((p_buf = (tBTA_AV_API_PROTECT_RSP *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_PROTECT_RSP) + len))) != NULL) { + /* Cap allocation size to avoid UINT16 overflow */ + alloc_size = sizeof(tBTA_AV_API_PROTECT_RSP) + len; + if (alloc_size > UINT16_MAX) { + return; + } + if ((p_buf = (tBTA_AV_API_PROTECT_RSP *) osi_malloc((UINT16) alloc_size)) != NULL) { p_buf->hdr.layer_specific = hndl; p_buf->hdr.event = BTA_AV_API_PROTECT_RSP_EVT; p_buf->len = len; @@ -452,8 +465,14 @@ void BTA_AvRemoteCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_RC rc_id, tBTA_AV_STA void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code, UINT8 *p_data, UINT16 len) { tBTA_AV_API_VENDOR *p_buf; + size_t alloc_size; - if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL) { + /* Cap allocation size to avoid UINT16 overflow */ + alloc_size = sizeof(tBTA_AV_API_VENDOR) + len; + if (alloc_size > UINT16_MAX) { + return; + } + if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) alloc_size)) != NULL) { p_buf->hdr.event = BTA_AV_API_VENDOR_CMD_EVT; p_buf->hdr.layer_specific = rc_handle; p_buf->msg.hdr.ctype = cmd_code; @@ -487,8 +506,14 @@ void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code, UINT8 void BTA_AvVendorRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code, UINT8 *p_data, UINT16 len, UINT32 company_id) { tBTA_AV_API_VENDOR *p_buf; + size_t alloc_size; - if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL) { + /* Cap allocation size to avoid UINT16 overflow */ + alloc_size = sizeof(tBTA_AV_API_VENDOR) + len; + if (alloc_size > 0xFFFF) { + return; + } + if ((p_buf = (tBTA_AV_API_VENDOR *) osi_malloc((UINT16) alloc_size)) != NULL) { p_buf->hdr.event = BTA_AV_API_VENDOR_RSP_EVT; p_buf->hdr.layer_specific = rc_handle; p_buf->msg.hdr.ctype = rsp_code; @@ -610,6 +635,8 @@ void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p p_buf->label = label; bta_sys_sendmsg(p_buf); + } else if (p_pkt) { + osi_free(p_pkt); } } @@ -672,14 +699,30 @@ void BTA_AvCaClose(UINT8 rc_handle) void BTA_AvCaGet(UINT8 rc_handle, tBTA_AV_GET_TYPE type, UINT8 *image_handle, UINT8 *image_descriptor, UINT16 image_descriptor_len) { tBTA_AV_API_CA_GET *p_buf; + size_t alloc_size; - if ((p_buf = (tBTA_AV_API_CA_GET *) osi_malloc(sizeof(tBTA_AV_API_CA_GET))) != NULL) { + /* NULL image_handle would cause crash in memcpy; reject early */ + if (image_handle == NULL) { + return; + } + /* Cap allocation size to avoid overflow */ + alloc_size = sizeof(tBTA_AV_API_CA_GET) + image_descriptor_len; + if (alloc_size > 0xFFFF) { + return; + } + if ((p_buf = (tBTA_AV_API_CA_GET *) osi_malloc((UINT16) alloc_size)) != NULL) { p_buf->hdr.event = BTA_AV_API_CA_GET_EVT; p_buf->hdr.layer_specific = rc_handle; p_buf->type = type; memcpy(p_buf->image_handle, image_handle, BTA_AV_CA_IMG_HDL_LEN); - p_buf->image_descriptor = image_descriptor; p_buf->image_descriptor_len = image_descriptor_len; + /* Copy image_descriptor into message to avoid use-after-free when message is async */ + if (image_descriptor != NULL && image_descriptor_len > 0) { + p_buf->image_descriptor = (UINT8 *) (p_buf + 1); + memcpy(p_buf->image_descriptor, image_descriptor, image_descriptor_len); + } else { + p_buf->image_descriptor = NULL; + } bta_sys_sendmsg(p_buf); } } diff --git a/components/bt/host/bluedroid/bta/av/bta_av_cfg.c b/components/bt/host/bluedroid/bta/av/bta_av_cfg.c index ef22d7932b1..a7b47b58856 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_cfg.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_cfg.c @@ -61,7 +61,7 @@ const UINT16 bta_av_audio_flush_to[] = { 0 /* 5 streams */ }; /* AVDTP audio transport channel flush timeout */ -/* Note: Android doesnt support AVRC_SUPF_TG_GROUP_NAVI */ +/* Note: Android doesn't support AVRC_SUPF_TG_GROUP_NAVI */ /* Note: if AVRC_SUPF_TG_GROUP_NAVI is set, bta_av_cfg.avrc_group should be TRUE */ #if AVRC_METADATA_INCLUDED == TRUE #define BTA_AV_RC_SNK_SUPF_TG (AVRC_SUPF_TG_CAT2) /* TODO: | AVRC_SUPF_TG_APP_SETTINGS) */ @@ -105,6 +105,6 @@ const tBTA_AV_CFG bta_av_cfg = { {0}, /* Default AVRCP target name */ }; -tBTA_AV_CFG *p_bta_av_cfg = (tBTA_AV_CFG *) &bta_av_cfg; +const tBTA_AV_CFG *p_bta_av_cfg = &bta_av_cfg; #endif /* if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE) */ diff --git a/components/bt/host/bluedroid/bta/av/bta_av_ci.c b/components/bt/host/bluedroid/bta/av/bta_av_ci.c index f1d2e9d0f72..8ffc3cdca5f 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_ci.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_ci.c @@ -82,7 +82,7 @@ void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, UINT8 category, p_buf->category = category; p_buf->recfg_needed = recfg_needed; p_buf->avdt_handle = avdt_handle; - p_buf->num_seid = num_seid; + p_buf->num_seid = (p_seid != NULL) ? num_seid : 0; if (p_seid && num_seid) { memcpy(p_buf->p_seid, p_seid, num_seid); } diff --git a/components/bt/host/bluedroid/bta/av/bta_av_main.c b/components/bt/host/bluedroid/bta/av/bta_av_main.c index 56dc5970a33..ae04faf1d18 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_main.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_main.c @@ -366,7 +366,12 @@ static tBTA_AV_SCB *bta_av_alloc_scb(tBTA_AV_CHNL chnl) p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl); p_ret->hdi = xx; p_ret->a2d_list = list_new(NULL); - bta_av_cb.p_scb[xx] = p_ret; + if (p_ret->a2d_list == NULL) { + osi_free(p_ret); + p_ret = NULL; + } else { + bta_av_cb.p_scb[xx] = p_ret; + } } break; } @@ -415,13 +420,15 @@ void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p p_scb = bta_av_addr_to_scb(bd_addr); } else if (AVDT_CONNECT_IND_EVT == event) { - APPL_TRACE_DEBUG("CONN_IND is ACP:%d\n", p_data->hdr.err_param); + if (p_data) { + APPL_TRACE_DEBUG("CONN_IND is ACP:%d\n", p_data->hdr.err_param); + } } if ((p_msg = (tBTA_AV_STR_MSG *) osi_malloc((UINT16) (sizeof(tBTA_AV_STR_MSG)))) != NULL) { p_msg->hdr.event = evt; p_msg->hdr.layer_specific = event; - p_msg->hdr.offset = p_data->hdr.err_param; + p_msg->hdr.offset = p_data ? p_data->hdr.err_param : 0; bdcpy(p_msg->bd_addr, bd_addr); if (p_scb) { APPL_TRACE_DEBUG("scb hndl x%x, role x%x\n", p_scb->hndl, p_scb->role); @@ -1177,9 +1184,9 @@ void bta_av_dup_audio_buf(tBTA_AV_SCB *p_scb, BT_HDR *p_buf) if (list_length(p_scbi->a2d_list) > p_bta_av_cfg->audio_mqs) { // Drop the oldest packet bta_av_co_audio_drop(p_scbi->hndl); - BT_HDR *p_buf = list_front(p_scbi->a2d_list); - list_remove(p_scbi->a2d_list, p_buf); - osi_free(p_buf); + BT_HDR *p_buf_drop = list_front(p_scbi->a2d_list); + list_remove(p_scbi->a2d_list, p_buf_drop); + osi_free(p_buf_drop); } } } @@ -1203,6 +1210,10 @@ void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data) tBTA_AV_ST_TBL state_table; UINT8 action; + if (p_cb == NULL || p_cb->state >= (sizeof(bta_av_st_tbl) / sizeof(bta_av_st_tbl[0]))) { + return; + } + APPL_TRACE_EVENT("AV event=0x%x state=%d\n", event, p_cb->state); /* look up the state table for the current state */ @@ -1210,6 +1221,10 @@ void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data) event &= 0x00FF; + if (event >= (sizeof(bta_av_st_init) / sizeof(bta_av_st_init[0]))) { + return; + } + /* set next state */ p_cb->state = state_table[event][BTA_AV_NEXT_STATE]; APPL_TRACE_EVENT("next state=%d\n", p_cb->state); @@ -1242,8 +1257,10 @@ BOOLEAN bta_av_hdl_event(BT_HDR *p_msg) if (event >= first_event) { APPL_TRACE_VERBOSE("AV nsm event=0x%x(%s)\n", event, bta_av_evt_code(event)); - /* non state machine events */ - (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg); + if (event <= BTA_AV_LAST_NSM_EVT) { + /* non state machine events */ + (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg); + } } else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT) { APPL_TRACE_VERBOSE("AV sm event=0x%x(%s)\n", event, bta_av_evt_code(event)); /* state machine events */ diff --git a/components/bt/host/bluedroid/bta/av/bta_av_sbc.c b/components/bt/host/bluedroid/bta/av/bta_av_sbc.c index 4e034c42461..44af221760c 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_sbc.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_sbc.c @@ -119,7 +119,9 @@ int bta_av_sbc_up_sample (void *p_src, void *p_dst, dst = dst_samples / bta_av_sbc_ups_cb.div; return (*bta_av_sbc_ups_cb.p_act)(p_src, p_dst, src, dst, p_ret); } else { - *p_ret = 0; + if (p_ret) { + *p_ret = 0; + } return 0; } } @@ -212,7 +214,7 @@ int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst, UINT32 src_sps = bta_av_sbc_ups_cb.src_sps; UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps; - while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) { + while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2) { *p_dst_tmp++ = *p_worker; *p_dst_tmp++ = *p_worker; @@ -224,7 +226,7 @@ int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst, bta_av_sbc_ups_cb.cur_pos = dst_sps; - while (src_samples-- && dst_samples) { + while (src_samples-- && dst_samples >= 2) { *p_worker = *p_src_tmp++; do { @@ -235,7 +237,7 @@ int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst, dst_samples--; dst_samples--; - } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples); + } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2); bta_av_sbc_ups_cb.cur_pos += dst_sps; } @@ -276,7 +278,7 @@ int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst, UINT32 src_sps = bta_av_sbc_ups_cb.src_sps; UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps; - while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) { + while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2) { *p_dst_tmp++ = *p_worker1; *p_dst_tmp++ = *p_worker2; @@ -287,7 +289,7 @@ int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst, bta_av_sbc_ups_cb.cur_pos = dst_sps; - while (src_samples -- && dst_samples) { + while (src_samples -- && dst_samples >= 2) { *p_worker1 = *(UINT8 *)p_src_tmp++; *p_worker1 -= 0x80; *p_worker1 <<= 8; @@ -302,7 +304,7 @@ int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst, bta_av_sbc_ups_cb.cur_pos -= src_sps; dst_samples--; dst_samples--; - } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples); + } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 2); bta_av_sbc_ups_cb.cur_pos += dst_sps; } @@ -342,7 +344,7 @@ int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst, UINT32 src_sps = bta_av_sbc_ups_cb.src_sps; UINT32 dst_sps = bta_av_sbc_ups_cb.dst_sps; - while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples) { + while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 4) { *p_dst_tmp++ = *p_worker; *p_dst_tmp++ = *p_worker; @@ -353,7 +355,7 @@ int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst, bta_av_sbc_ups_cb.cur_pos = dst_sps; - while (src_samples-- && dst_samples) { + while (src_samples-- && dst_samples >= 4) { *p_worker = *(UINT8 *)p_src_tmp++; *p_worker -= 0x80; *p_worker <<= 8; @@ -365,7 +367,7 @@ int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst, bta_av_sbc_ups_cb.cur_pos -= src_sps; dst_samples -= 4; - } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples); + } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples >= 4); bta_av_sbc_ups_cb.cur_pos += dst_sps; } @@ -455,6 +457,11 @@ UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p peer_cie.min_bitpool = p_pref->min_bitpool; } + if (peer_cie.min_bitpool > peer_cie.max_bitpool) { + APPL_TRACE_ERROR("bta_av_sbc_cfg_for_cap: min_bp > max_bp"); + return A2D_FAIL; + } + if (status == A2D_SUCCESS) { /* build configuration */ A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &peer_cie, p_peer); diff --git a/components/bt/host/bluedroid/bta/av/bta_av_ssm.c b/components/bt/host/bluedroid/bta/av/bta_av_ssm.c index 15acf51386e..4f6dbd8a8fa 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_ssm.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_ssm.c @@ -429,6 +429,11 @@ void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data) APPL_TRACE_VERBOSE("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)", p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state)); + if (p_scb->state >= (sizeof(bta_av_sst_tbl) / sizeof(bta_av_sst_tbl[0])) || + event < BTA_AV_FIRST_SSM_EVT || event > BTA_AV_LAST_SSM_EVT) { + return; + } + /* look up the state table for the current state */ state_table = bta_av_sst_tbl[p_scb->state]; diff --git a/components/bt/host/bluedroid/bta/av/include/bta_av_int.h b/components/bt/host/bluedroid/bta/av/include/bta_av_int.h index 90c86dea180..cf0aba81d52 100644 --- a/components/bt/host/bluedroid/bta/av/include/bta_av_int.h +++ b/components/bt/host/bluedroid/bta/av/include/bta_av_int.h @@ -132,6 +132,7 @@ enum { /* events for AV stream control block state machine */ #define BTA_AV_FIRST_SSM_EVT BTA_AV_API_OPEN_EVT +#define BTA_AV_LAST_SSM_EVT BTA_AV_ACP_CONNECT_EVT /* events that do not go through state machine */ #define BTA_AV_FIRST_NSM_EVT BTA_AV_API_ENABLE_EVT @@ -667,7 +668,7 @@ extern tBTA_AV_CB *bta_av_cb_ptr; #endif /* config struct */ -extern tBTA_AV_CFG *p_bta_av_cfg; +extern const tBTA_AV_CFG *p_bta_av_cfg; extern const tBTA_AV_SACT bta_av_a2d_action[]; extern const tBTA_AV_SACT bta_av_vdp_action[]; diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c index 1ac66da463c..5027e6bcc3d 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/bta_av_co.c @@ -297,6 +297,7 @@ void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk, /* Sanity check : this should never happen */ if (p_peer->opened) { APPL_TRACE_ERROR("bta_av_co_audio_disc_res peer already opened"); + return; } /* Copy the discovery results */ @@ -347,6 +348,7 @@ void bta_av_co_audio_cfg_res(tBTA_AV_HNDL hndl, UINT8 num_seps, UINT8 num_snk, /* Sanity check : this should never happen */ if (p_peer->opened) { APPL_TRACE_ERROR("bta_av_co_audio_cfg_res peer already opened"); + return; } /* Copy the discovery results */ @@ -391,6 +393,8 @@ void bta_av_build_src_cfg (UINT8 *p_pref_cfg, UINT8 *p_src_cap) return ; } + memcpy(&pref_cap, &src_cap, sizeof(tA2D_SBC_CIE)); + if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_48) { pref_cap.samp_freq = A2D_SBC_IE_SAMP_FREQ_48; } else if (src_cap.samp_freq & A2D_SBC_IE_SAMP_FREQ_44) { @@ -739,6 +743,8 @@ void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, /* Sanity check: should not be opened at this point */ if (p_peer->opened) { APPL_TRACE_ERROR("bta_av_co_audio_setconfig peer already in use"); + bta_av_ci_setconfig(hndl, A2D_BUSY, AVDT_ASC_CODEC, 0, NULL, FALSE, avdt_handle); + return; } #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) @@ -984,7 +990,7 @@ void *bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type, UINT32 *p_len, #if defined(BTA_AV_CO_CP_SCMS_T) && (BTA_AV_CO_CP_SCMS_T == TRUE) { UINT8 *p; - if (bta_av_co_cp_is_active()) { + if (bta_av_co_cp_is_active() && p_buf->offset > 0) { p_buf->len++; p_buf->offset--; p = (UINT8 *)(p_buf + 1) + p_buf->offset; diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c index ba264f93866..d7ecf1b5912 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_control.c @@ -76,7 +76,9 @@ static void btc_a2dp_datapath_open(void) } #endif #if (BTC_AV_SINK_INCLUDED == TRUE) - btc_aa_ctrl_cb.data_channel_open = TRUE; + if (btc_av_get_peer_sep() == AVDT_TSEP_SRC && btc_av_get_service_id() == BTA_A2DP_SINK_SERVICE_ID) { + btc_aa_ctrl_cb.data_channel_open = TRUE; + } #endif } diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index f389a524816..f244903aaa0 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -418,6 +418,7 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg a2dp_sink_local_param.btc_aa_snk_cb.channel_count, FALSE, FALSE); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); + return; } btc_a2dp_control_set_datachnl_stat(TRUE); @@ -528,7 +529,7 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg *******************************************************************************/ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg) { - UINT8 *sbc_start_frame = ((UINT8 *)(p_msg + 1) + p_msg->offset + 1); + UINT8 *sbc_start_frame; int count; UINT32 pcmBytes, availPcmBytes; OI_INT16 *pcmDataPointer = a2dp_sink_local_param.pcmData; /*Will be overwritten on next packet receipt*/ @@ -574,8 +575,6 @@ static void btc_a2dp_sink_handle_inc_media(tBT_SBC_HDR *p_msg) } availPcmBytes -= pcmBytes; pcmDataPointer += pcmBytes / 2; - p_msg->offset += (p_msg->len - 1) - sbc_frame_len; - p_msg->len = sbc_frame_len + 1; } if (count != num_sbc_frames || sbc_frame_len) { APPL_TRACE_WARNING("Potential decoding error, cnt:%d, num:%d, len:%d. Please ignore if playback is normal.", diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c index d388e94a6c8..7e483049019 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c @@ -377,10 +377,12 @@ void btc_a2dp_source_on_stopped(tBTA_AV_SUSPEND *p_av) void btc_a2dp_source_on_suspended(tBTA_AV_SUSPEND *p_av) { - /* check for status failures */ - if (p_av->status != BTA_AV_SUCCESS) { - if (p_av->initiator == TRUE) { - btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE); + if (p_av != NULL) { + /* check for status failures */ + if (p_av->status != BTA_AV_SUCCESS) { + if (p_av->initiator == TRUE) { + btc_a2dp_control_command_ack(ESP_A2D_MEDIA_CTRL_ACK_FAILURE); + } } } @@ -678,15 +680,24 @@ static void btc_a2dp_source_encoder_init(void) /* lookup table to convert freq */ UINT16 freq_block_tbl[5] = { SBC_sf48000, SBC_sf44100, SBC_sf32000, 0, SBC_sf16000 }; + UINT8 block_idx, mode_idx, freq_idx; + APPL_TRACE_DEBUG("%s", __FUNCTION__); /* Retrieve the current SBC configuration (default if currently not used) */ bta_av_co_audio_get_sbc_config(&sbc_config, &minmtu); msg.NumOfSubBands = (sbc_config.num_subbands == A2D_SBC_IE_SUBBAND_4) ? 4 : 8; - msg.NumOfBlocks = codec_block_tbl[sbc_config.block_len >> 5]; + + block_idx = sbc_config.block_len >> 5; + msg.NumOfBlocks = (block_idx < 5) ? codec_block_tbl[block_idx] : 16; + msg.AllocationMethod = (sbc_config.alloc_mthd == A2D_SBC_IE_ALLOC_MD_L) ? SBC_LOUDNESS : SBC_SNR; - msg.ChannelMode = codec_mode_tbl[sbc_config.ch_mode >> 1]; - msg.SamplingFreq = freq_block_tbl[sbc_config.samp_freq >> 5]; + + mode_idx = sbc_config.ch_mode >> 1; + msg.ChannelMode = (mode_idx < 5) ? codec_mode_tbl[mode_idx] : SBC_JOINT_STEREO; + + freq_idx = sbc_config.samp_freq >> 5; + msg.SamplingFreq = (freq_idx < 5) ? freq_block_tbl[freq_idx] : SBC_sf44100; msg.MtuSize = minmtu; APPL_TRACE_EVENT("msg.ChannelMode %x", msg.ChannelMode); @@ -1108,6 +1119,10 @@ static UINT8 btc_get_num_aa_frame(void) a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.num_channel * a2dp_source_local_param.btc_aa_src_cb.media_feeding.cfg.pcm.bit_per_sample / 8; + if (pcm_bytes_per_frame == 0) { + break; + } + UINT32 us_this_tick = BTC_MEDIA_TIME_TICK_MS * 1000; UINT64 now_us = time_now_us(); if (a2dp_source_local_param.last_frame_us != 0) { @@ -1302,9 +1317,9 @@ BOOLEAN btc_media_aa_read_feeding(void) a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue -= bytes_needed; if (a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue != 0) { - memcpy((UINT8 *)up_sampled_buffer, - (UINT8 *)up_sampled_buffer + bytes_needed, - a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue); + memmove((UINT8 *)up_sampled_buffer, + (UINT8 *)up_sampled_buffer + bytes_needed, + a2dp_source_local_param.btc_aa_src_cb.media_feeding_state.pcm.aa_feed_residue); } return TRUE; } @@ -1424,7 +1439,10 @@ static void btc_a2dp_source_prep_2_send(UINT8 nb_frame) } while (fixed_queue_length(a2dp_source_local_param.btc_aa_src_cb.TxAaQ) > (MAX_OUTPUT_A2DP_SRC_FRAME_QUEUE_SZ - nb_frame)) { - osi_free(fixed_queue_dequeue(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, 0)); + void *p_drop = fixed_queue_dequeue(a2dp_source_local_param.btc_aa_src_cb.TxAaQ, 0); + if (p_drop != NULL) { + osi_free(p_drop); + } } // Transcode frame @@ -1539,8 +1557,8 @@ static void btc_a2dp_source_aa_stop_tx(void) when the DUT and the remote device issue SUSPEND simultaneously and due to the processing of the SUSPEND request from the remote, the media path is torn down. If the A2DP HAL happens to wait - for ACK for the initiated SUSPEND, it would never receive it casuing - a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed + for ACK for the initiated SUSPEND, it would never receive it causing + a block/wait. Due to this acknowledgement, the A2DP HAL is guaranteed to get the ACK for any pending command in such cases. */ if (send_ack) { diff --git a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c index 2193a549dde..90e9ba114e6 100644 --- a/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c +++ b/components/bt/host/bluedroid/btc/profile/std/a2dp/btc_av.c @@ -308,6 +308,7 @@ static void btc_report_audio_state(esp_a2d_audio_state_t state, bt_bdaddr_t *bd_ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) { esp_a2d_cb_param_t param; + memset(¶m, 0, sizeof(esp_a2d_cb_param_t)); BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); @@ -387,6 +388,10 @@ static BOOLEAN btc_av_state_idle_handler(btc_sm_event_t event, void *p_data) */ #if BTC_AV_SRC_INCLUDED BTC_TRACE_DEBUG("BTA_AV_RC_OPEN_EVT received w/o AV"); + if (btc_av_cb.tle_av_open_on_rc) { + osi_alarm_free(btc_av_cb.tle_av_open_on_rc); + btc_av_cb.tle_av_open_on_rc = NULL; + } btc_av_cb.tle_av_open_on_rc = osi_alarm_new("AVconn", btc_initiate_av_open_tmr_hdlr, NULL, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000); osi_alarm_set(btc_av_cb.tle_av_open_on_rc, BTC_TIMEOUT_AV_OPEN_ON_RC_SECS * 1000); #endif /* BTC_AV_SRC_INCLUDED */ @@ -521,9 +526,10 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) } } break; - case BTC_AV_CONNECT_REQ_EVT: + case BTC_AV_CONNECT_REQ_EVT: { + btc_av_connect_req_t *connect_req = (btc_av_connect_req_t *)p_data; // Check for device, if same device which moved to opening then ignore callback - if (memcmp ((bt_bdaddr_t *)p_data, &(btc_av_cb.peer_bda), + if (memcmp (&connect_req->target_bda, &(btc_av_cb.peer_bda), sizeof(btc_av_cb.peer_bda)) == 0) { BTC_TRACE_DEBUG("%s: Same device moved to Opening state,ignore Connect Req\n", __func__); btc_queue_advance(); @@ -534,6 +540,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) btc_queue_advance(); break; } + } case BTA_AV_PENDING_EVT: // Check for device, if same device which moved to opening then ignore callback @@ -592,6 +599,7 @@ static BOOLEAN btc_av_state_opening_handler(btc_sm_event_t event, void *p_data) static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data) { esp_a2d_cb_param_t param; + memset(¶m, 0, sizeof(esp_a2d_cb_param_t)); BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); @@ -679,6 +687,7 @@ static BOOLEAN btc_av_state_closing_handler(btc_sm_event_t event, void *p_data) static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) { esp_a2d_cb_param_t param; + memset(¶m, 0, sizeof(esp_a2d_cb_param_t)); tBTA_AV *p_av = (tBTA_AV *)p_data; BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__, @@ -801,8 +810,9 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) } break; - case BTC_AV_CONNECT_REQ_EVT: - if (memcmp (&((btc_av_connect_req_t *)p_data)->target_bda, &(btc_av_cb.peer_bda), + case BTC_AV_CONNECT_REQ_EVT: { + btc_av_connect_req_t *connect_req = (btc_av_connect_req_t *)p_data; + if (memcmp (&connect_req->target_bda, &(btc_av_cb.peer_bda), sizeof(btc_av_cb.peer_bda)) == 0) { BTC_TRACE_DEBUG("%s: Ignore BTC_AVCONNECT_REQ_EVT for same device\n", __func__); } else { @@ -812,6 +822,7 @@ static BOOLEAN btc_av_state_opened_handler(btc_sm_event_t event, void *p_data) } btc_queue_advance(); break; + } CHECK_RC_EVENT(event, p_data); @@ -855,6 +866,7 @@ static BOOLEAN btc_av_state_started_handler(btc_sm_event_t event, void *p_data) { tBTA_AV *p_av = (tBTA_AV *)p_data; esp_a2d_cb_param_t param; + memset(¶m, 0, sizeof(esp_a2d_cb_param_t)); BTC_TRACE_DEBUG("%s event: %s flags %x\n", __FUNCTION__, dump_av_sm_event_name(event), btc_av_cb.flags); diff --git a/components/bt/host/bluedroid/stack/a2dp/a2d_api.c b/components/bt/host/bluedroid/stack/a2dp/a2d_api.c index 87ff14c39b0..661673eb5ea 100644 --- a/components/bt/host/bluedroid/stack/a2dp/a2d_api.c +++ b/components/bt/host/bluedroid/stack/a2dp/a2d_api.c @@ -66,6 +66,8 @@ static void a2d_sdp_cback(UINT16 status) A2D_TRACE_API("a2d_sdp_cback status: %d", status); + memset(&a2d_svc, 0, sizeof(tA2D_Service)); + if (status == SDP_SUCCESS) { /* loop through all records we found */ do { @@ -74,7 +76,6 @@ static void a2d_sdp_cback(UINT16 status) a2d_cb.find.service_uuid, p_rec)) == NULL) { break; } - memset(&a2d_svc, 0, sizeof(tA2D_Service)); /* get service name */ if ((p_attr = SDP_FindAttributeInRec(p_rec, diff --git a/components/bt/host/bluedroid/stack/a2dp/a2d_sbc.c b/components/bt/host/bluedroid/stack/a2dp/a2d_sbc.c index d02dd384f76..8b6578aec43 100644 --- a/components/bt/host/bluedroid/stack/a2dp/a2d_sbc.c +++ b/components/bt/host/bluedroid/stack/a2dp/a2d_sbc.c @@ -107,14 +107,15 @@ tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps) { tA2D_STATUS status = A2D_SUCCESS; UINT8 losc; + UINT8 media_type; if ( p_ie == NULL || p_info == NULL) { status = A2D_INVALID_PARAMS; } else { losc = *p_info++; - p_info++; + media_type = *p_info++; /* If the function is called for the wrong Media Type or Media Codec Type */ - if (losc != A2D_SBC_INFO_LEN || *p_info != A2D_MEDIA_CT_SBC) { + if (losc != A2D_SBC_INFO_LEN || media_type != A2D_MEDIA_TYPE_AUDIO || *p_info != A2D_MEDIA_CT_SBC) { status = A2D_WRONG_CODEC; } else { p_info++; @@ -129,14 +130,10 @@ tA2D_STATUS A2D_ParsSbcInfo(tA2D_SBC_CIE *p_ie, UINT8 *p_info, BOOLEAN for_caps) p_ie->max_bitpool = *p_info; if (p_ie->min_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->min_bitpool > A2D_SBC_IE_MAX_BITPOOL ) { status = A2D_BAD_MIN_BITPOOL; - } - - if (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL || - p_ie->max_bitpool < p_ie->min_bitpool) { + } else if (p_ie->max_bitpool < A2D_SBC_IE_MIN_BITPOOL || p_ie->max_bitpool > A2D_SBC_IE_MAX_BITPOOL || + p_ie->max_bitpool < p_ie->min_bitpool) { status = A2D_BAD_MAX_BITPOOL; - } - - if (for_caps == FALSE) { + } else if (for_caps == FALSE) { if (A2D_BitsSet(p_ie->samp_freq) != A2D_SET_ONE_BIT) { status = A2D_BAD_SAMP_FREQ; } else if (A2D_BitsSet(p_ie->ch_mode) != A2D_SET_ONE_BIT) { diff --git a/components/bt/host/bluedroid/stack/avct/avct_api.c b/components/bt/host/bluedroid/stack/avct/avct_api.c index 7826eaa5d22..09ce64e8184 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_api.c +++ b/components/bt/host/bluedroid/stack/avct/avct_api.c @@ -62,6 +62,9 @@ void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask) AVCT_TRACE_API("AVCT_Register"); + /* initialize AVCTP data structures */ + memset(&avct_cb, 0, sizeof(tAVCT_CB)); + /* register PSM with L2CAP */ L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_appl); @@ -69,9 +72,6 @@ void AVCT_Register(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask) BTM_SetSecurityLevel(TRUE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0); BTM_SetSecurityLevel(FALSE, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0, 0); - /* initialize AVCTP data structures */ - memset(&avct_cb, 0, sizeof(tAVCT_CB)); - #if (AVCT_BROWSE_INCLUDED == TRUE) /* Include the browsing channel which uses eFCR */ L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO *) &avct_l2c_br_appl); @@ -142,6 +142,10 @@ UINT16 AVCT_CreateConn(UINT8 *p_handle, tAVCT_CC *p_cc, BD_ADDR peer_addr) tAVCT_CCB *p_ccb; tAVCT_LCB *p_lcb; + if (p_cc == NULL || p_handle == NULL) { + return AVCT_BAD_HANDLE; + } + AVCT_TRACE_API("AVCT_CreateConn: %d, control:%d", p_cc->role, p_cc->control); /* Allocate ccb; if no ccbs, return failure */ @@ -234,7 +238,7 @@ UINT16 AVCT_CreateBrowse (UINT8 handle, UINT8 role) #if (AVCT_BROWSE_INCLUDED == TRUE) UINT16 result = AVCT_SUCCESS; tAVCT_CCB *p_ccb; - tAVCT_BCB *p_bcb; + tAVCT_BCB *p_bcb = NULL; int index; AVCT_TRACE_API("AVCT_CreateBrowse: %d", role); @@ -428,7 +432,12 @@ UINT16 AVCT_MsgReq(UINT8 handle, UINT8 label, UINT8 cr, BT_HDR *p_msg) osi_free(p_msg); } else { p_ccb->p_bcb = avct_bcb_by_lcb(p_ccb->p_lcb); - avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg); + if (p_ccb->p_bcb == NULL) { + result = AVCT_BAD_HANDLE; + osi_free(p_msg); + } else { + avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_MSG_EVT, (tAVCT_LCB_EVT *) &ul_msg); + } } } /* send msg event to lcb */ diff --git a/components/bt/host/bluedroid/stack/avct/avct_ccb.c b/components/bt/host/bluedroid/stack/avct/avct_ccb.c index 8cc9fc39969..01f0d56f076 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_ccb.c +++ b/components/bt/host/bluedroid/stack/avct/avct_ccb.c @@ -83,7 +83,7 @@ void avct_ccb_dealloc(tAVCT_CCB *p_ccb, UINT8 event, UINT16 result, BD_ADDR bd_a if (p_ccb->p_bcb == NULL) { memset(p_ccb, 0, sizeof(tAVCT_CCB)); } else { - /* control channel is down, but the browsing channel is still connected 0 disconnect it now */ + /* control channel is down, but the browsing channel is still connected - disconnect it now */ avct_bcb_event(p_ccb->p_bcb, AVCT_LCB_UL_UNBIND_EVT, (tAVCT_LCB_EVT *) &p_ccb); p_ccb->p_lcb = NULL; } diff --git a/components/bt/host/bluedroid/stack/avct/avct_l2c.c b/components/bt/host/bluedroid/stack/avct/avct_l2c.c index a501b15755c..d6896e18095 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_l2c.c +++ b/components/bt/host/bluedroid/stack/avct/avct_l2c.c @@ -124,6 +124,7 @@ void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 } else { /* TG role only - accept the connection from CT. move the channel ID to the conflict list */ p_lcb->conflict_lcid = p_lcb->ch_lcid; + p_lcb->ch_flags = 0; AVCT_TRACE_DEBUG("avct_l2c_connect_ind_cback conflict_lcid:0x%x", p_lcb->conflict_lcid); } } @@ -142,6 +143,7 @@ void avct_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 /* transition to configuration state */ p_lcb->ch_state = AVCT_CH_CFG; + p_lcb->ch_flags = 0; /* Send L2CAP config req */ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); @@ -183,6 +185,7 @@ void avct_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result) if (result == L2CAP_CONN_OK) { /* set channel state */ p_lcb->ch_state = AVCT_CH_CFG; + p_lcb->ch_flags = 0; /* Send L2CAP config req */ memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO)); @@ -275,6 +278,10 @@ void avct_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg) /* look up lcb for this channel */ if ((p_lcb = avct_lcb_by_lcid(lcid)) != NULL) { AVCT_TRACE_DEBUG("avct_l2c_config_ind_cback: 0x%x, ch_state: %d", lcid, p_lcb->ch_state); + if (p_lcb->ch_state != AVCT_CH_CFG) { + AVCT_TRACE_ERROR("avct_l2c_config_ind_cback: EINVAL state %d", p_lcb->ch_state); + return; + } /* store the mtu in tbl */ if (p_cfg->mtu_present) { p_lcb->peer_mtu = p_cfg->mtu; diff --git a/components/bt/host/bluedroid/stack/avct/avct_lcb.c b/components/bt/host/bluedroid/stack/avct/avct_lcb.c index 84a0f021258..ab19b1b4ce7 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_lcb.c +++ b/components/bt/host/bluedroid/stack/avct/avct_lcb.c @@ -310,10 +310,16 @@ tAVCT_LCB *avct_lcb_alloc(BD_ADDR bd_addr) for (i = 0; i < AVCT_NUM_LINKS; i++, p_lcb++) { if (!p_lcb->allocated) { + memset(p_lcb, 0, sizeof(tAVCT_LCB)); p_lcb->allocated = (UINT8)(i + 1); memcpy(p_lcb->peer_addr, bd_addr, BD_ADDR_LEN); AVCT_TRACE_DEBUG("avct_lcb_alloc %d", p_lcb->allocated); p_lcb->tx_q = fixed_queue_new(QUEUE_SIZE_MAX); + if (p_lcb->tx_q == NULL) { + AVCT_TRACE_ERROR("avct_lcb_alloc: failed to create tx_q"); + memset(p_lcb, 0, sizeof(tAVCT_LCB)); + p_lcb = NULL; + } break; } } diff --git a/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c b/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c index 98dbaed809c..97d81b497ee 100644 --- a/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c +++ b/components/bt/host/bluedroid/stack/avct/avct_lcb_act.c @@ -63,6 +63,11 @@ static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf) p = (UINT8 *)(p_buf + 1) + p_buf->offset; AVCT_PRS_PKT_TYPE(p, pkt_type); + if (pkt_type > AVCT_PKT_TYPE_END) { + osi_free(p_buf); + return NULL; + } + /* quick sanity check on length */ if (p_buf->len < avct_lcb_pkt_type_len[pkt_type]) { osi_free(p_buf); @@ -114,6 +119,11 @@ static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf) /* set offset to point to where to copy next */ p_lcb->p_rx_msg->offset += p_lcb->p_rx_msg->len; + if (p_lcb->p_rx_msg->len < 1) { + osi_free(p_lcb->p_rx_msg); + p_lcb->p_rx_msg = NULL; + return NULL; + } /* adjust length for packet header */ p_lcb->p_rx_msg->len -= 1; } @@ -146,6 +156,11 @@ static BT_HDR *avct_lcb_msg_asmbl(tAVCT_LCB *p_lcb, BT_HDR *p_buf) p_lcb->p_rx_msg = NULL; osi_free(p_buf); p_ret = NULL; + } else if ((UINT32)p_lcb->p_rx_msg->len + p_buf->len > 0xFFFF) { + osi_free(p_lcb->p_rx_msg); + p_lcb->p_rx_msg = NULL; + osi_free(p_buf); + p_ret = NULL; } else { /* copy contents of p_buf to p_rx_msg */ memcpy((UINT8 *)(p_lcb->p_rx_msg + 1) + p_lcb->p_rx_msg->offset, @@ -541,6 +556,7 @@ void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data) /* whoops; free original msg buf and bail */ AVCT_TRACE_ERROR ("avct_lcb_send_msg cannot alloc buffer!!"); osi_free(p_data->ul_msg.p_buf); + p_data->ul_msg.p_buf = NULL; break; } @@ -555,6 +571,7 @@ void avct_lcb_send_msg(tAVCT_LCB *p_lcb, tAVCT_LCB_EVT *p_data) p_data->ul_msg.p_buf->len -= p_buf->len; } else { p_buf = p_data->ul_msg.p_buf; + p_data->ul_msg.p_buf = NULL; } curr_msg_len -= p_buf->len; diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_ad.c b/components/bt/host/bluedroid/stack/avdt/avdt_ad.c index b24c952d902..d6911e1f7cf 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_ad.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_ad.c @@ -54,6 +54,9 @@ UINT8 avdt_ad_type_to_tcid(UINT8 type, tAVDT_SCB *p_scb) if (type == AVDT_CHAN_SIG) { return 0; } else { + if (p_scb == NULL) { + return 0; + } scb_idx = avdt_scb_to_hdl(p_scb) - 1; /* AVDT_TRACE_DEBUG("type: %d, tcid: %d", type, ((scb_idx * (AVDT_CHAN_NUM_TYPES - 1)) + type)); @@ -186,8 +189,19 @@ tAVDT_TC_TBL *avdt_ad_tc_tbl_by_st(UINT8 type, tAVDT_CCB *p_ccb, UINT8 state) tAVDT_TC_TBL *avdt_ad_tc_tbl_by_lcid(UINT16 lcid) { UINT8 idx; + UINT16 lcid_offset; - idx = avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID]; + if (lcid < L2CAP_BASE_APPL_CID) { + return NULL; + } + + lcid_offset = lcid - L2CAP_BASE_APPL_CID; + + if (lcid_offset >= MAX_L2CAP_CHANNELS) { + return NULL; + } + + idx = avdt_cb.ad.lcid_tbl[lcid_offset]; if (idx < AVDT_NUM_TC_TBL) { return &avdt_cb.ad.tc_tbl[idx]; @@ -316,6 +330,9 @@ void avdt_ad_tc_close_ind(tAVDT_TC_TBL *p_tbl, UINT16 reason) /* if signaling channel, notify ccb that channel open */ if (p_tbl->tcid == 0) { p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); + if (p_ccb == NULL) { + return; + } p_ccb->disc_rsn = (reason == AVDT_DISC_RSN_ABNORMAL) ? AVDT_DISC_RSN_ABNORMAL : AVDT_DISC_RSN_NORMAL; avdt_ccb_event(p_ccb, AVDT_CCB_LL_CLOSE_EVT, NULL); } @@ -359,6 +376,9 @@ void avdt_ad_tc_open_ind(tAVDT_TC_TBL *p_tbl) L2CA_SetTxPriority(avdt_cb.ad.rt_tbl[p_tbl->ccb_idx][AVDT_CHAN_SIG].lcid, L2CAP_CHNL_PRIORITY_HIGH); p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); + if (p_ccb == NULL) { + return; + } /* use err_param to indicate the role of connection. * AVDT_ACP, if ACP */ evt.err_param = AVDT_INT; @@ -405,6 +425,9 @@ void avdt_ad_tc_cong_ind(tAVDT_TC_TBL *p_tbl, BOOLEAN is_congested) /* if signaling channel, notify ccb of congestion */ if (p_tbl->tcid == 0) { p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); + if (p_ccb == NULL) { + return; + } avdt_ccb_event(p_ccb, AVDT_CCB_LL_CONG_EVT, (tAVDT_CCB_EVT *) &is_congested); } /* if media or other channel, notify scb that channel open */ @@ -442,6 +465,10 @@ void avdt_ad_tc_data_ind(tAVDT_TC_TBL *p_tbl, BT_HDR *p_buf) /* if signaling channel, handle control message */ if (p_tbl->tcid == 0) { p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx); + if (p_ccb == NULL) { + osi_free(p_buf); + return; + } avdt_msg_ind(p_ccb, p_buf); } /* if media or other channel, send event to scb */ @@ -534,7 +561,7 @@ void avdt_ad_open_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb, UINT8 role if (role == AVDT_ACP) { p_tbl->state = AVDT_AD_ST_ACP; } - /* else we're inititator, start the L2CAP connection */ + /* else we're initiator, start the L2CAP connection */ else { p_tbl->state = AVDT_AD_ST_CONN; @@ -574,6 +601,9 @@ void avdt_ad_close_req(UINT8 type, tAVDT_CCB *p_ccb, tAVDT_SCB *p_scb) tAVDT_TC_TBL *p_tbl; p_tbl = avdt_ad_tc_tbl_by_type(type, p_ccb, p_scb); + if (p_tbl == NULL) { + return; + } AVDT_TRACE_DEBUG("avdt_ad_close_req state: %d\n", p_tbl->state); switch (p_tbl->state) { diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_api.c b/components/bt/host/bluedroid/stack/avdt/avdt_api.c index f37db816548..5ad577ce978 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_api.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_api.c @@ -110,6 +110,9 @@ void avdt_process_timeout(TIMER_LIST_ENT *p_tle) *******************************************************************************/ void AVDT_Register(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback) { + if (p_reg == NULL || p_cback == NULL) { + return; + } /* register PSM with L2CAP */ L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO *) &avdt_l2c_appl); @@ -251,6 +254,9 @@ UINT16 AVDT_CreateStream(UINT8 *p_handle, tAVDT_CS *p_cs) UINT16 result = AVDT_SUCCESS; tAVDT_SCB *p_scb; + if (p_handle == NULL) { + return AVDT_BAD_PARAMS; + } /* Verify parameters; if invalid, return failure */ if (((p_cs->cfg.psc_mask & (~AVDT_PSC)) != 0) || (p_cs->p_ctrl_cback == NULL)) { result = AVDT_BAD_PARAMS; @@ -898,6 +904,9 @@ UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_ tAVDT_SCB_EVT evt; UINT16 result = AVDT_SUCCESS; + if (p_pkt == NULL) { + return AVDT_BAD_PARAMS; + } /* map handle to scb */ if ((p_scb = avdt_scb_by_hdl(handle)) == NULL) { result = AVDT_BAD_HANDLE; @@ -1157,7 +1166,7 @@ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type, /* build SR - assume fit in one packet */ p_tbl = avdt_ad_tc_tbl_by_type(AVDT_CHAN_REPORT, p_scb->p_ccb, p_scb); - if ((p_tbl->state == AVDT_AD_ST_OPEN) && + if ((p_tbl != NULL) && (p_tbl->state == AVDT_AD_ST_OPEN) && (p_pkt = (BT_HDR *)osi_malloc(p_tbl->peer_mtu)) != NULL) { p_pkt->offset = L2CAP_MIN_OFFSET; p = (UINT8 *)(p_pkt + 1) + p_pkt->offset; @@ -1190,9 +1199,12 @@ UINT16 AVDT_SendReport(UINT8 handle, AVDT_REPORT_TYPE type, case AVDT_RTCP_PT_RR: /* Receiver Report */ *p++ = p_data->rr.frag_lost; AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); - p_data->rr.packet_lost &= 0xFFFFFF; - AVDT_TRACE_API("packet_lost: %d\n", p_data->rr.packet_lost); - UINT24_TO_BE_STREAM(p, p_data->rr.packet_lost); + /* Use local 24-bit value so caller's p_data->rr.packet_lost is not mutated */ + { + UINT32 packet_lost_24 = p_data->rr.packet_lost & 0xFFFFFF; + AVDT_TRACE_API("packet_lost_24: %d\n", packet_lost_24); + UINT24_TO_BE_STREAM(p, packet_lost_24); + } UINT32_TO_BE_STREAM(p, p_data->rr.seq_num_rcvd); UINT32_TO_BE_STREAM(p, p_data->rr.jitter); UINT32_TO_BE_STREAM(p, p_data->rr.lsr); diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c b/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c index 035488f8545..bf8943aa54c 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_ccb.c @@ -31,6 +31,7 @@ #include "stack/avdtc_api.h" #include "avdt_int.h" #include "stack/btu.h" +#include "osi/allocator.h" #if (defined(AVDT_INCLUDED) && AVDT_INCLUDED == TRUE) @@ -302,6 +303,10 @@ void avdt_ccb_event(tAVDT_CCB *p_ccb, UINT8 event, tAVDT_CCB_EVT *p_data) UINT8 action; int i; + if (p_ccb == NULL || p_ccb->state > AVDT_CCB_CLOSING_ST || event > AVDT_CCB_LL_CONG_EVT) { + return; + } + #if AVDT_DEBUG == TRUE AVDT_TRACE_EVENT("CCB ccb=%d event=%s state=%s\n", avdt_ccb_to_idx(p_ccb), avdt_ccb_evt_str[event], avdt_ccb_st_str[p_ccb->state]); #endif @@ -396,7 +401,7 @@ tAVDT_CCB *avdt_ccb_alloc(BD_ADDR bd_addr) ** ** Function avdt_ccb_dealloc ** -** Description Deallocate a stream control block. +** Description Deallocate a channel control block. ** ** ** Returns void. @@ -406,10 +411,28 @@ void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { UNUSED(p_data); + if (p_ccb == NULL) { + return; + } + AVDT_TRACE_DEBUG("avdt_ccb_dealloc %d\n", avdt_ccb_to_idx(p_ccb)); + btu_free_timer(&p_ccb->timer_entry); - fixed_queue_free(p_ccb->cmd_q, NULL); - fixed_queue_free(p_ccb->rsp_q, NULL); + fixed_queue_free(p_ccb->cmd_q, osi_free_func); + fixed_queue_free(p_ccb->rsp_q, osi_free_func); + + if (p_ccb->p_curr_cmd != NULL) { + osi_free(p_ccb->p_curr_cmd); + p_ccb->p_curr_cmd = NULL; + } + if (p_ccb->p_curr_msg != NULL) { + osi_free(p_ccb->p_curr_msg); + p_ccb->p_curr_msg = NULL; + } + if (p_ccb->p_rx_msg != NULL) { + osi_free(p_ccb->p_rx_msg); + p_ccb->p_rx_msg = NULL; + } memset(p_ccb, 0, sizeof(tAVDT_CCB)); } @@ -425,6 +448,9 @@ void avdt_ccb_dealloc(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) *******************************************************************************/ UINT8 avdt_ccb_to_idx(tAVDT_CCB *p_ccb) { + if (p_ccb == NULL) { + return AVDT_NUM_LINKS; + } /* use array arithmetic to determine index */ return (UINT8) (p_ccb - avdt_cb.ccb); } @@ -446,6 +472,9 @@ tAVDT_CCB *avdt_ccb_by_idx(UINT8 idx) /* verify index */ if (idx < AVDT_NUM_LINKS) { p_ccb = &avdt_cb.ccb[idx]; + if (!p_ccb->allocated) { + p_ccb = NULL; + } } else { p_ccb = NULL; AVDT_TRACE_WARNING("No ccb for idx %d\n", idx); diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c b/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c index 7d7e7c6e77c..dce084aa7c5 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_ccb_act.c @@ -218,10 +218,21 @@ void avdt_ccb_hdl_discover_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) void avdt_ccb_hdl_getcap_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) { tAVDT_SCB *p_scb; + UINT8 sig_id = AVDT_SIG_GETCAP; /* look up scb for seid sent to us */ p_scb = avdt_scb_by_hdl(p_data->msg.single.seid); + if (p_scb == NULL) { + p_data->msg.hdr.err_code = AVDT_ERR_SEID; + p_data->msg.hdr.err_param = p_data->msg.single.seid; + if (p_data->msg.hdr.sig_id == AVDT_SIG_GET_ALLCAP) { + sig_id = AVDT_SIG_GET_ALLCAP; + } + avdt_msg_send_rej(p_ccb, sig_id, &p_data->msg); + return; + } + p_data->msg.svccap.p_cfg = &p_scb->cs.cfg; avdt_ccb_event(p_ccb, AVDT_CCB_API_GETCAP_RSP_EVT, p_data); @@ -300,6 +311,10 @@ void avdt_ccb_hdl_start_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) UINT8 *p; tAVDT_SCB *p_scb; + if (p_ccb->p_curr_cmd == NULL) { + return; + } + /* determine rsp or rej event */ event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_START_RSP_EVT : AVDT_SCB_MSG_START_REJ_EVT; @@ -369,6 +384,10 @@ void avdt_ccb_hdl_suspend_rsp(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) UINT8 *p; tAVDT_SCB *p_scb; + if (p_ccb->p_curr_cmd == NULL) { + return; + } + /* determine rsp or rej event */ event = (p_data->msg.hdr.err_code == 0) ? AVDT_SCB_MSG_SUSPEND_RSP_EVT : AVDT_SCB_MSG_SUSPEND_REJ_EVT; @@ -505,13 +524,15 @@ void avdt_ccb_snd_start_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) tAVDT_MSG avdt_msg; UINT8 seid_list[AVDT_NUM_SEPS]; + p_data->msg.multi.num_seps = (p_data->msg.multi.num_seps > AVDT_NUM_SEPS) ? + AVDT_NUM_SEPS : p_data->msg.multi.num_seps; /* make copy of our seid list */ memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps); /* verify all streams in the right state */ if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_OPEN, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0) { - /* set peer seid list in messsage */ + /* set peer seid list in message */ avdt_scb_peer_seid_list(&p_data->msg.multi); /* send command */ @@ -576,13 +597,15 @@ void avdt_ccb_snd_suspend_cmd(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) tAVDT_MSG avdt_msg; UINT8 seid_list[AVDT_NUM_SEPS]; + p_data->msg.multi.num_seps = (p_data->msg.multi.num_seps > AVDT_NUM_SEPS) ? + AVDT_NUM_SEPS : p_data->msg.multi.num_seps; /* make copy of our seid list */ memcpy(seid_list, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps); /* verify all streams in the right state */ if ((avdt_msg.hdr.err_param = avdt_scb_verify(p_ccb, AVDT_VERIFY_STREAMING, p_data->msg.multi.seid_list, p_data->msg.multi.num_seps, &avdt_msg.hdr.err_code)) == 0) { - /* set peer seid list in messsage */ + /* set peer seid list in message */ avdt_scb_peer_seid_list(&p_data->msg.multi); /* send command */ @@ -690,6 +713,12 @@ void avdt_ccb_cmd_fail(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) tAVDT_SCB *p_scb; if (p_ccb->p_curr_cmd != NULL) { + if (p_ccb->p_curr_cmd->event < 1 || p_ccb->p_curr_cmd->event > AVDT_SIG_MAX) { + osi_free(p_ccb->p_curr_cmd); + p_ccb->p_curr_cmd = NULL; + return; + } + /* set up data */ msg.hdr.err_code = p_data->err_code; msg.hdr.err_param = 0; @@ -1076,7 +1105,7 @@ void avdt_ccb_ll_opened(tAVDT_CCB *p_ccb, tAVDT_CCB_EVT *p_data) /* call callback */ if (p_ccb->p_conn_cback) { avdt_ctrl.hdr.err_code = 0; - avdt_ctrl.hdr.err_param = p_data->msg.hdr.err_param; + avdt_ctrl.hdr.err_param = (p_data != NULL) ? p_data->msg.hdr.err_param : 0; (*p_ccb->p_conn_cback)(0, p_ccb->peer_addr, AVDT_CONNECT_IND_EVT, &avdt_ctrl); } } diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_l2c.c b/components/bt/host/bluedroid/stack/avdt/avdt_l2c.c index c7c1e58ac45..b163d0e8842 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_l2c.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_l2c.c @@ -79,6 +79,7 @@ static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transpo tL2CAP_CFG_INFO cfg; tAVDT_TC_TBL *p_tbl; UNUSED(p_ref_data); + UNUSED(transport); AVDT_TRACE_DEBUG("avdt_sec_check_complete_term res: %d\n", res); if (!bd_addr) { @@ -97,9 +98,11 @@ static void avdt_sec_check_complete_term (BD_ADDR bd_addr, tBT_TRANSPORT transpo /* Send response to the L2CAP layer. */ L2CA_ConnectRsp (bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK, L2CAP_CONN_OK); - /* store idx in LCID table, store LCID in routing table */ - avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); - avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid; + if (p_tbl->lcid >= L2CAP_BASE_APPL_CID && (p_tbl->lcid - L2CAP_BASE_APPL_CID) < MAX_L2CAP_CHANNELS) { + /* store idx in LCID table, store LCID in routing table */ + avdt_cb.ad.lcid_tbl[p_tbl->lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); + avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = p_tbl->lcid; + } /* transition to configuration state */ p_tbl->state = AVDT_AD_ST_CFG; @@ -134,11 +137,13 @@ static void avdt_sec_check_complete_orig (BD_ADDR bd_addr, tBT_TRANSPORT transpo tL2CAP_CFG_INFO cfg; tAVDT_TC_TBL *p_tbl; UNUSED(p_ref_data); + UNUSED(transport); AVDT_TRACE_DEBUG("avdt_sec_check_complete_orig res: %d\n", res); if (bd_addr) { p_ccb = avdt_ccb_by_bd(bd_addr); } + p_tbl = avdt_ad_tc_tbl_by_st(AVDT_CHAN_SIG, p_ccb, AVDT_AD_ST_SEC_INT); if (p_tbl == NULL) { return; @@ -188,6 +193,11 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 } else { /* allocate and set up entry; first channel is always signaling */ p_tbl = avdt_ad_tc_tbl_alloc(p_ccb); + if (p_tbl == NULL) { + avdt_ccb_dealloc(p_ccb, NULL); + L2CA_ConnectRsp(bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0); + return; + } p_tbl->my_mtu = avdt_cb.rcb.ctrl_mtu; p_tbl->my_flush_to = L2CAP_DEFAULT_FLUSH_TO; p_tbl->tcid = AVDT_CHAN_SIG; @@ -238,10 +248,11 @@ void avdt_l2c_connect_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 /* if result ok, proceed with connection */ if (result == L2CAP_CONN_OK) { - /* store idx in LCID table, store LCID in routing table */ - avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); - avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; - + if (lcid >= L2CAP_BASE_APPL_CID && lcid < (L2CAP_BASE_APPL_CID + MAX_L2CAP_CHANNELS)) { + /* store idx in LCID table, store LCID in routing table */ + avdt_cb.ad.lcid_tbl[lcid - L2CAP_BASE_APPL_CID] = avdt_ad_tc_tbl_to_idx(p_tbl); + avdt_cb.ad.rt_tbl[avdt_ccb_to_idx(p_ccb)][p_tbl->tcid].lcid = lcid; + } /* transition to configuration state */ p_tbl->state = AVDT_AD_ST_CFG; @@ -420,13 +431,12 @@ void avdt_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed) if (ack_needed) { /* send L2CAP disconnect response */ L2CA_DisconnectRsp(lcid); - } else { - if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) { - UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR); - if (rsn != 0 && rsn != HCI_ERR_PEER_USER) { - disc_rsn = AVDT_DISC_RSN_ABNORMAL; - AVDT_TRACE_EVENT("avdt link disc rsn 0x%x", rsn); - } + } + if ((p_ccb = avdt_ccb_by_idx(p_tbl->ccb_idx)) != NULL) { + UINT16 rsn = L2CA_GetDisconnectReason(p_ccb->peer_addr, BT_TRANSPORT_BR_EDR); + if (rsn != 0 && rsn != HCI_ERR_PEER_USER) { + disc_rsn = AVDT_DISC_RSN_ABNORMAL; + AVDT_TRACE_EVENT("avdt link disc rsn 0x%x", rsn); } } diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_msg.c b/components/bt/host/bluedroid/stack/avdt/avdt_msg.c index 74b7b791846..b5eee31792c 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_msg.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_msg.c @@ -462,8 +462,10 @@ static void avdt_msg_bld_multi(UINT8 **p, tAVDT_MSG *p_msg) static void avdt_msg_bld_security_cmd(UINT8 **p, tAVDT_MSG *p_msg) { AVDT_MSG_BLD_SEID(*p, p_msg->security_cmd.hdr.seid); - memcpy(*p, p_msg->security_cmd.p_data, p_msg->security_cmd.len); - *p += p_msg->security_cmd.len; + if (p_msg->security_cmd.p_data && p_msg->security_cmd.len > 0) { + memcpy(*p, p_msg->security_cmd.p_data, p_msg->security_cmd.len); + *p += p_msg->security_cmd.len; + } } /******************************************************************************* @@ -625,6 +627,11 @@ static UINT8 avdt_msg_prs_cfg(tAVDT_CFG *p_cfg, UINT8 *p, UINT16 len, UINT8 *p_e } } + if ((size_t)(p_end - p) < elem_len) { + err = AVDT_ERR_LENGTH; + break; + } + if ((elem_len > avdt_msg_ie_len_max[elem]) || (elem_len < avdt_msg_ie_len_min[elem])) { err = avdt_msg_ie_err[elem]; @@ -975,12 +982,19 @@ static UINT8 avdt_msg_prs_discover_rsp(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len) int i; UINT8 err = 0; + if (p_msg->discover_rsp.p_sep_info == NULL) { + return AVDT_ERR_BAD_STATE; + } + /* determine number of seps; seps in msg is len/2, but set to minimum ** of seps app has supplied memory for and seps in msg */ if (p_msg->discover_rsp.num_seps > (len / 2)) { p_msg->discover_rsp.num_seps = (len / 2); } + if (p_msg->discover_rsp.num_seps > AVDT_NUM_SEPS) { + p_msg->discover_rsp.num_seps = AVDT_NUM_SEPS; + } /* parse out sep info */ for (i = 0; i < p_msg->discover_rsp.num_seps; i++) { @@ -1018,6 +1032,8 @@ static UINT8 avdt_msg_prs_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len) UINT8 err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GETCAP); if (p_msg->svccap.p_cfg) { p_msg->svccap.p_cfg->psc_mask &= AVDT_LEG_PSC; + } else { + return AVDT_ERR_BAD_STATE; } return (err); @@ -1039,6 +1055,8 @@ static UINT8 avdt_msg_prs_all_svccap(tAVDT_MSG *p_msg, UINT8 *p, UINT16 len) UINT8 err = avdt_msg_prs_cfg(p_msg->svccap.p_cfg, p, len, &p_msg->hdr.err_param, AVDT_SIG_GET_ALLCAP); if (p_msg->svccap.p_cfg) { p_msg->svccap.p_cfg->psc_mask &= AVDT_MSG_PSC_MASK; + } else { + return AVDT_ERR_BAD_STATE; } return (err); } @@ -1152,6 +1170,10 @@ BOOLEAN avdt_msg_send(tAVDT_CCB *p_ccb, BT_HDR *p_msg) p_ccb->p_curr_msg = p_msg; } + if (p_ccb->p_curr_msg == NULL) { + return FALSE; + } + /* store copy of curr_msg->len */ curr_msg_len = p_ccb->p_curr_msg->len; @@ -1368,10 +1390,16 @@ BT_HDR *avdt_msg_asmbl(tAVDT_CCB *p_ccb, BT_HDR *p_buf) (UINT8 *)(p_buf + 1) + p_buf->offset, p_buf->len); if (pkt_type == AVDT_PKT_TYPE_END) { - p_ccb->p_rx_msg->offset -= p_ccb->p_rx_msg->len; - p_ccb->p_rx_msg->len += p_buf->len; - p_ret = p_ccb->p_rx_msg; - p_ccb->p_rx_msg = NULL; + if (p_ccb->p_rx_msg->len <= p_ccb->p_rx_msg->offset) { + p_ccb->p_rx_msg->offset -= p_ccb->p_rx_msg->len; + p_ccb->p_rx_msg->len += p_buf->len; + p_ret = p_ccb->p_rx_msg; + p_ccb->p_rx_msg = NULL; + } else { + osi_free(p_ccb->p_rx_msg); + p_ccb->p_rx_msg = NULL; + p_ret = NULL; + } } else { p_ccb->p_rx_msg->offset += p_buf->len; p_ccb->p_rx_msg->len += p_buf->len; @@ -1405,6 +1433,10 @@ void avdt_msg_send_cmd(tAVDT_CCB *p_ccb, void *p_scb, UINT8 sig_id, tAVDT_MSG *p UINT8 *p; UINT8 *p_start; + if (sig_id < AVDT_SIG_DISCOVER || sig_id > AVDT_SIG_MAX) { + return; + } + /* get a buffer */ p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE); if (p_buf == NULL) { @@ -1470,6 +1502,10 @@ void avdt_msg_send_rsp(tAVDT_CCB *p_ccb, UINT8 sig_id, tAVDT_MSG *p_params) UINT8 *p; UINT8 *p_start; + if (sig_id < AVDT_SIG_DISCOVER || sig_id > AVDT_SIG_MAX) { + return; + } + /* get a buffer */ p_buf = (BT_HDR *) osi_malloc(AVDT_CMD_BUF_SIZE); if (p_buf == NULL) { @@ -1656,7 +1692,11 @@ void avdt_msg_ind(tAVDT_CCB *p_ccb, BT_HDR *p_buf) gen_rej = TRUE; if (p_ccb->p_curr_cmd != NULL) { msg.hdr.sig_id = sig = (UINT8) p_ccb->p_curr_cmd->event; - evt = avdt_msg_rej_2_evt[sig - 1]; + if (sig >= AVDT_SIG_DISCOVER && sig <= AVDT_SIG_MAX) { + evt = avdt_msg_rej_2_evt[sig - 1]; + } else { + ok = FALSE; + } msg.hdr.err_code = AVDT_ERR_NSC; msg.hdr.err_param = 0; } diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_scb.c b/components/bt/host/bluedroid/stack/avdt/avdt_scb.c index ca1e9f4c0fd..dbebc48ae9a 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_scb.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_scb.c @@ -541,6 +541,10 @@ void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data) UINT8 action; int i; + if (p_scb == NULL || p_scb->state > AVDT_SCB_CLOSING_ST || event > AVDT_SCB_DELAY_RPT_RSP_TOUT_EVT) { + return; + } + #if AVDT_DEBUG == TRUE AVDT_TRACE_EVENT("SCB hdl=%d event=%d/%s state=%s\n", avdt_scb_to_hdl(p_scb), event, avdt_scb_evt_str[event], avdt_scb_st_str[p_scb->state]); #endif @@ -558,7 +562,9 @@ void avdt_scb_event(tAVDT_SCB *p_scb, UINT8 event, tAVDT_SCB_EVT *p_data) /* execute action functions */ for (i = 0; i < AVDT_SCB_ACTIONS; i++) { if ((action = state_table[event][i]) != AVDT_SCB_IGNORE) { - (*avdt_cb.p_scb_act[action])(p_scb, p_data); + if (action < AVDT_SCB_NUM_ACTIONS) { + (*avdt_cb.p_scb_act[action])(p_scb, p_data); + } } else { break; } diff --git a/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c b/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c index 5fae98eed8a..d0209c5d1a8 100644 --- a/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c +++ b/components/bt/host/bluedroid/stack/avdt/avdt_scb_act.c @@ -273,6 +273,9 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) /* skip over any csrc's in packet */ offset += o_cc * 4; p += o_cc * 4; + if (len < offset) { + goto length_error; + } /* check for and skip over extension header */ if (o_x) { @@ -283,6 +286,9 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) } p += 2; BE_STREAM_TO_UINT16(ex_len, p); + if ((UINT32)ex_len * 4 > (UINT32)(len - offset)) { + goto length_error; + } p += ex_len * 4; } @@ -317,12 +323,12 @@ void avdt_scb_hdl_pkt_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) #if AVDT_MULTIPLEXING == TRUE if ((p_scb->cs.p_media_cback != NULL) && (p_scb->p_media_buf != NULL) - && (p_scb->media_buf_len > len)) { + && (p_scb->media_buf_len > p_data->p_pkt->len)) { /* media buffer enough length is assigned by application. Lets use it*/ memcpy(p_scb->p_media_buf, (UINT8 *)(p_data->p_pkt + 1) + p_data->p_pkt->offset, - len); + p_data->p_pkt->len); (*p_scb->cs.p_media_cback)(avdt_scb_to_hdl(p_scb), p_scb->p_media_buf, - p_scb->media_buf_len, time_stamp, seq, m_pt, marker); + p_data->p_pkt->len, time_stamp, seq, m_pt, marker); } #endif goto length_error; @@ -355,6 +361,8 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len) AVDT_REPORT_TYPE pt; tAVDT_REPORT_DATA report; + memset(&report, 0, sizeof(report)); + AVDT_TRACE_DEBUG( "avdt_scb_hdl_report"); if (p_scb->cs.p_report_cback) { /* parse report packet header */ @@ -417,7 +425,7 @@ UINT8 *avdt_scb_hdl_report(tAVDT_SCB *p_scb, UINT8 *p, UINT16 len) goto avdt_scb_hdl_report_exit; } uint8_t name_length; - BE_STREAM_TO_UINT8(name_length, p);\ + BE_STREAM_TO_UINT8(name_length, p); if ((name_length > len - min_len) || (name_length > AVDT_MAX_CNAME_SIZE)) { result = AVDT_BAD_PARAMS; } else { @@ -643,6 +651,11 @@ void avdt_scb_hdl_pkt_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) pad_len = 0; } /* payload length */ + if ((pad_len + p_payload) >= (p_scb->p_media_buf + p_scb->frag_off)) { + AVDT_TRACE_WARNING("length check3 p_payload:%p pad_len:%d p_media_buf:%p frag_off:%d", + p_payload, pad_len, p_scb->p_media_buf, p_scb->frag_off); + break; + } payload_len = (UINT32)(p_scb->p_media_buf + p_scb->frag_off - pad_len - p_payload); AVDT_TRACE_DEBUG("Received last fragment header=%d len=%d\n", @@ -1054,10 +1067,13 @@ void avdt_scb_hdl_tc_close(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) tAVDT_CTRL avdt_ctrl; UINT8 event; tAVDT_CCB *p_ccb = p_scb->p_ccb; - BD_ADDR remote_addr; + BD_ADDR remote_addr; - - memcpy (remote_addr, p_ccb->peer_addr, BD_ADDR_LEN); + if (p_ccb != NULL) { + memcpy(remote_addr, p_ccb->peer_addr, BD_ADDR_LEN); + } else { + memset(remote_addr, 0, BD_ADDR_LEN); + } /* set up hdr */ avdt_ctrl.hdr.err_code = p_scb->close_code; @@ -1331,6 +1347,12 @@ void avdt_scb_hdl_write_req_no_frag(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) if ( !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP) ) { ssrc = avdt_scb_gen_ssrc(p_scb); + if (p_data->apiwrite.p_buf->offset < AVDT_MEDIA_HDR_SIZE) { + osi_free(p_data->apiwrite.p_buf); + p_data->apiwrite.p_buf = NULL; + return; + } + p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE; p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE; p_scb->media_seq++; @@ -1838,6 +1860,11 @@ void avdt_scb_cb_err(tAVDT_SCB *p_scb, tAVDT_SCB_EVT *p_data) avdt_ctrl.hdr.err_code = AVDT_ERR_BAD_STATE; avdt_ctrl.hdr.err_param = 0; + if (p_scb->curr_evt >= (sizeof(avdt_scb_cback_evt) / sizeof(avdt_scb_cback_evt[0]))) { + AVDT_TRACE_ERROR("avdt_scb_cb_err curr_evt %u OOR", p_scb->curr_evt); + return; + } + /* call callback, using lookup table to get callback event */ (*p_scb->cs.p_ctrl_cback)(avdt_scb_to_hdl(p_scb), NULL,