From 9b6e661aba48ce915467063d1451672e7162f4d1 Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Thu, 8 Jan 2026 09:36:46 +0800 Subject: [PATCH 1/6] fix(bt/bluedroid): A2DP source at acceptor side will miss ESP_A2D_AUDIO_CFG_EVT --- .../bt/host/bluedroid/bta/av/bta_av_aact.c | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) 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 2e4f5ec078..a23f4e5f87 100644 --- a/components/bt/host/bluedroid/bta/av/bta_av_aact.c +++ b/components/bt/host/bluedroid/bta/av/bta_av_aact.c @@ -1277,19 +1277,19 @@ void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) bta_av_adjust_seps_idx(p_scb, avdt_handle); APPL_TRACE_DEBUG("bta_av_setconfig_rsp: sep_idx: %d cur_psc_mask:0x%x", p_scb->sep_idx, p_scb->cur_psc_mask); + if ((p_data->ci_setconfig.err_code == AVDT_SUCCESS) && + (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL)) { + p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, + (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); + } + if (AVDT_TSEP_SNK == local_sep) { - if ((p_data->ci_setconfig.err_code == AVDT_SUCCESS) && - (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL)) { - p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, - (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); - } if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) { psc_cfg.psc_mask |= BTA_AV_PSC_DEALY_RPT; } (*bta_av_cb.p_cback)(BTA_AV_SNK_PSC_CFG_EVT, (tBTA_AV *)&psc_cfg); } - AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, p_data->ci_setconfig.err_code, p_data->ci_setconfig.category); @@ -1908,24 +1908,18 @@ void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data) cfg.psc_mask &= p_scb->p_cap->psc_mask; p_scb->cur_psc_mask = cfg.psc_mask; + if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) { + APPL_TRACE_DEBUG(" Configure Deoder for A2DP Connection "); + p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, + (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); + } + if (uuid_int == UUID_SERVCLASS_AUDIO_SINK) { - if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) { - APPL_TRACE_DEBUG(" Configure Deoder for Sink Connection "); - p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, - (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); - } if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT) { psc_cfg.psc_mask |= BTA_AV_PSC_DEALY_RPT; } (*bta_av_cb.p_cback)(BTA_AV_SNK_PSC_CFG_EVT, (tBTA_AV *)&psc_cfg); } - else { - /* UUID_SERVCLASS_AUDIO_SOURCE */ - if (p_scb->seps[p_scb->sep_idx].p_app_data_cback != NULL) { - p_scb->seps[p_scb->sep_idx].p_app_data_cback(BTA_AV_MEDIA_CFG_EVT, - (tBTA_AV_MEDIA *)p_scb->cfg.codec_info); - } - } /* open the stream */ AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr, From 41edf56707305e05967db566cf39ec16227c6a6b Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Mon, 22 Dec 2025 16:47:18 +0800 Subject: [PATCH 2/6] fix(bt): validated UUID parameters in BTA_JvStartDiscovery --- components/bt/host/bluedroid/bta/jv/bta_jv_api.c | 5 +++++ .../bt/host/bluedroid/btc/profile/std/spp/btc_spp.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/components/bt/host/bluedroid/bta/jv/bta_jv_api.c b/components/bt/host/bluedroid/bta/jv/bta_jv_api.c index 7fb74fdfa8..cfa0ff9091 100644 --- a/components/bt/host/bluedroid/bta/jv/bta_jv_api.c +++ b/components/bt/host/bluedroid/bta/jv/bta_jv_api.c @@ -283,6 +283,11 @@ tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid, tBTA_JV_API_START_DISCOVERY *p_msg; APPL_TRACE_API( "BTA_JvStartDiscovery"); + if ((num_uuid > BTA_JV_MAX_UUIDS) || ((num_uuid > 0) && (p_uuid_list == NULL))) { + APPL_TRACE_ERROR("invalid uuid list: num_uuid=%u", num_uuid); + return BTA_JV_FAILURE; + } + if ((p_msg = (tBTA_JV_API_START_DISCOVERY *)osi_malloc(sizeof(tBTA_JV_API_START_DISCOVERY))) != NULL) { p_msg->hdr.event = BTA_JV_API_START_DISCOVERY_EVT; bdcpy(p_msg->bd_addr, bd_addr); diff --git a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c index 31a71992dc..3426688edd 100644 --- a/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.c +++ b/components/bt/host/bluedroid/btc/profile/std/spp/btc_spp.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 */ @@ -652,7 +652,11 @@ static void btc_spp_start_discovery(btc_spp_args_t *arg) ret = ESP_SPP_NEED_INIT; break; } - BTA_JvStartDiscovery(arg->start_discovery.bd_addr, arg->start_discovery.num_uuid, arg->start_discovery.p_uuid_list, NULL); + tBTA_JV_STATUS status = BTA_JvStartDiscovery(arg->start_discovery.bd_addr, arg->start_discovery.num_uuid, arg->start_discovery.p_uuid_list, NULL); + if (status != BTA_JV_SUCCESS) { + BTC_TRACE_ERROR("%s SPP failed to start discovery\n", __func__); + ret = ESP_SPP_NO_RESOURCE; + } } while (0); if (ret != ESP_SPP_SUCCESS) { From 0126907574f52339f716067cde4e9fb41001ce5b Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Mon, 22 Dec 2025 17:11:29 +0800 Subject: [PATCH 3/6] fix(bt): enhanced packet length check for HCI module --- components/bt/host/bluedroid/hci/hci_hal_h4.c | 4 ++++ components/bt/host/bluedroid/hci/hci_layer.c | 19 +++++++++++++++++++ .../bluedroid/hci/include/hci/hci_internals.h | 4 ++++ .../bt/host/bluedroid/hci/packet_fragmenter.c | 11 +++++++++++ 4 files changed, 38 insertions(+) diff --git a/components/bt/host/bluedroid/hci/hci_hal_h4.c b/components/bt/host/bluedroid/hci/hci_hal_h4.c index cadf70005f..475af54302 100644 --- a/components/bt/host/bluedroid/hci/hci_hal_h4.c +++ b/components/bt/host/bluedroid/hci/hci_hal_h4.c @@ -481,6 +481,10 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet) packet->len--; if (type == HCI_BLE_EVENT) { #if (!CONFIG_BT_STACK_NO_LOG) + if (packet->len < 1) { + osi_free(packet); + return; + } uint8_t len = 0; STREAM_TO_UINT8(len, stream); #endif diff --git a/components/bt/host/bluedroid/hci/hci_layer.c b/components/bt/host/bluedroid/hci/hci_layer.c index c6a6efa4ee..2ed3172c25 100644 --- a/components/bt/host/bluedroid/hci/hci_layer.c +++ b/components/bt/host/bluedroid/hci/hci_layer.c @@ -447,12 +447,26 @@ static bool filter_incoming_event(BT_HDR *packet) uint8_t event_code; command_opcode_t opcode; + if (packet == NULL) { + return true; + } + + if (packet->len < HCI_EVENT_PREAMBLE_SIZE) { + HCI_TRACE_WARNING("dropping too short HCI event (len=%u)", packet->len); + osi_free(packet); + return true; + } STREAM_TO_UINT8(event_code, stream); STREAM_SKIP_UINT8(stream); // Skip the parameter total length field HCI_TRACE_DEBUG("Receive packet event_code=0x%x\n", event_code); if (event_code == HCI_COMMAND_COMPLETE_EVT) { + if (packet->len < HCI_EVENT_PREAMBLE_SIZE + HCI_CC_EVENT_MIN_PARAM_LEN) { + HCI_TRACE_WARNING("dropping too short Command Complete (len=%u)", packet->len); + osi_free(packet); + return true; + } STREAM_TO_UINT8(hci_host_env.command_credits, stream); STREAM_TO_UINT16(opcode, stream); wait_entry = get_waiting_command(opcode); @@ -481,6 +495,11 @@ static bool filter_incoming_event(BT_HDR *packet) goto intercepted; } else if (event_code == HCI_COMMAND_STATUS_EVT) { uint8_t status; + if (packet->len < HCI_EVENT_PREAMBLE_SIZE + HCI_CS_EVENT_MIN_PARAM_LEN) { + HCI_TRACE_WARNING("dropping too short Command Status (len=%u)", packet->len); + osi_free(packet); + return true; + } STREAM_TO_UINT8(status, stream); STREAM_TO_UINT8(hci_host_env.command_credits, stream); STREAM_TO_UINT16(opcode, stream); diff --git a/components/bt/host/bluedroid/hci/include/hci/hci_internals.h b/components/bt/host/bluedroid/hci/include/hci/hci_internals.h index 41c792cf3c..7d336e8a13 100644 --- a/components/bt/host/bluedroid/hci/include/hci/hci_internals.h +++ b/components/bt/host/bluedroid/hci/include/hci/hci_internals.h @@ -27,5 +27,9 @@ #define HCI_SCO_PREAMBLE_SIZE 3 // 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4) #define HCI_EVENT_PREAMBLE_SIZE 2 +// 1 byte for Num_HCI_Command_Packets, 2 bytes for Commnad_Opcode (Volume 4, Part E, 7.7.14) +#define HCI_CC_EVENT_MIN_PARAM_LEN 3 +// 1 byte for status, 1 byte for Num_HCI_Command_Packets, 2 bytes for Commnad_Opcode (Volume 4, Part E, 7.7.15) +#define HCI_CS_EVENT_MIN_PARAM_LEN 4 #endif /* _HCI_INTERNALS_H_ */ diff --git a/components/bt/host/bluedroid/hci/packet_fragmenter.c b/components/bt/host/bluedroid/hci/packet_fragmenter.c index ccc220fbf1..0827ecb4fe 100644 --- a/components/bt/host/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/host/bluedroid/hci/packet_fragmenter.c @@ -37,6 +37,7 @@ #define START_PACKET_BOUNDARY 2 #define CONTINUATION_PACKET_BOUNDARY 1 #define L2CAP_HEADER_SIZE 4 +#define L2CAP_LENGTH_SIZE 2 // TODO(zachoverflow): find good value for this #define NUMBER_OF_BUCKETS 42 @@ -81,6 +82,11 @@ static void fragment_and_dispatch(BT_HDR *packet) callbacks->fragmented(packet, true); return; } + if (packet->len < HCI_ACL_PREAMBLE_SIZE) { + HCI_TRACE_ERROR("ACL packet too short for preamble (len=%u)", packet->len); + callbacks->fragmented(packet, true); + return; + } max_data_size = SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ? @@ -143,6 +149,11 @@ static void reassemble_and_dispatch(BT_HDR *packet) uint16_t l2cap_length; uint16_t acl_length __attribute__((unused)); + if (packet->len < HCI_ACL_PREAMBLE_SIZE + L2CAP_LENGTH_SIZE) { + HCI_TRACE_ERROR("ACL packet too short (len=%u)\n", packet->len); + osi_free(packet); + return; + } STREAM_TO_UINT16(handle, stream); STREAM_TO_UINT16(acl_length, stream); STREAM_TO_UINT16(l2cap_length, stream); From 458150888d7267403f673afca6fbbe4cab31c30b Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Mon, 22 Dec 2025 17:16:45 +0800 Subject: [PATCH 4/6] fix(bt): enhanced packet length check for avrc_pars_vendor_cmd --- .../host/bluedroid/stack/avrc/avrc_pars_tg.c | 74 ++++++++++--------- 1 file changed, 41 insertions(+), 33 deletions(-) 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 cae87a2a9e..0e967877fb 100644 --- a/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c +++ b/components/bt/host/bluedroid/stack/avrc/avrc_pars_tg.c @@ -106,46 +106,54 @@ static tAVRC_STS avrc_pars_vendor_cmd(tAVRC_MSG_VENDOR *p_msg, tAVRC_COMMAND *p_ case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */ case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */ - BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p); - if (len != (p_result->get_cur_app_val.num_attr + 1)) { + if (len < 1) { status = AVRC_STS_INTERNAL_ERR; - break; - } - p_u8 = p_result->get_cur_app_val.attrs; - 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; + } else { + BE_STREAM_TO_UINT8 (p_result->get_cur_app_val.num_attr, p); + if (len != (p_result->get_cur_app_val.num_attr + 1)) { + status = AVRC_STS_INTERNAL_ERR; + break; + } + p_u8 = p_result->get_cur_app_val.attrs; + 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; + } + p++; + } + p_result->get_cur_app_val.num_attr = yy; + if (yy == 0) { + status = AVRC_STS_BAD_PARAM; } - p++; - } - p_result->get_cur_app_val.num_attr = yy; - if (yy == 0) { - status = AVRC_STS_BAD_PARAM; } break; case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */ - 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++) { - 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)) { - status = AVRC_STS_BAD_PARAM; - } - } - if (xx != p_result->set_app_val.num_val) { - AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d", - xx, p_result->set_app_val.num_val); - p_result->set_app_val.num_val = xx; - } - } else { - AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len"); + if (len < 1) { 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++) { + 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)) { + status = AVRC_STS_BAD_PARAM; + } + } + if (xx != p_result->set_app_val.num_val) { + AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE not enough room:%d orig num_val:%d", + xx, p_result->set_app_val.num_val); + p_result->set_app_val.num_val = xx; + } + } else { + AVRC_TRACE_ERROR("AVRC_PDU_SET_PLAYER_APP_VALUE NULL decode buffer or bad len"); + status = AVRC_STS_INTERNAL_ERR; + } } break; From 46baa2dac17650dfbaf7ff954cd3a62dd0127a64 Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Mon, 22 Dec 2025 17:33:45 +0800 Subject: [PATCH 5/6] fix(bt): enhanced packet length check in sdp_server.c --- .../bt/host/bluedroid/stack/sdp/sdp_server.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/components/bt/host/bluedroid/stack/sdp/sdp_server.c b/components/bt/host/bluedroid/stack/sdp/sdp_server.c index 43e3664baf..d36b4115c9 100644 --- a/components/bt/host/bluedroid/stack/sdp/sdp_server.c +++ b/components/bt/host/bluedroid/stack/sdp/sdp_server.c @@ -118,6 +118,10 @@ void sdp_server_handle_client_req (tCONN_CB *p_ccb, BT_HDR *p_msg) UINT8 pdu_id; UINT16 trans_num, param_len; + if (p_msg->len < 5) { + SDP_TRACE_WARNING("SDP - short request received: len=%u\n", p_msg->len); + return; + } /* Start inactivity timer */ btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT); @@ -187,6 +191,11 @@ static void process_service_search (tCONN_CB *p_ccb, UINT16 trans_num, return; } + if (p_req + 2 > p_req_end) { + sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_RECORDS_LIST); + return; + } + /* Get the max replies we can send. Cap it at our max anyways. */ BE_STREAM_TO_UINT16 (max_replies, p_req); @@ -194,7 +203,6 @@ static void process_service_search (tCONN_CB *p_ccb, UINT16 trans_num, max_replies = SDP_MAX_RECORDS; } - if ((!p_req) || (p_req > p_req_end)) { sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_RECORDS_LIST); return; @@ -322,14 +330,13 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, BOOLEAN is_cont = FALSE; UINT16 attr_len; - /* Extract the record handle */ - BE_STREAM_TO_UINT32 (rec_handle, p_req); - - if (p_req > p_req_end) { + if (p_req + 4 + 2 > p_req_end) { sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_SERV_REC_HDL, SDP_TEXT_BAD_HANDLE); return; } + /* Extract the record handle */ + BE_STREAM_TO_UINT32 (rec_handle, p_req); /* Get the max list length we can send. Cap it at MTU size minus overhead */ BE_STREAM_TO_UINT16 (max_list_len, p_req); @@ -371,7 +378,7 @@ static void process_service_attr_req (tCONN_CB *p_ccb, UINT16 trans_num, return; } - if (*p_req++ != SDP_CONTINUATION_LEN) { + if ((*p_req++ != SDP_CONTINUATION_LEN) || (p_req + 2 > p_req_end)) { sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_CONT_STATE, SDP_TEXT_BAD_CONT_LEN); return; } From e421e7d2c0d72a2e9e9e4edbd403787a2e013f78 Mon Sep 17 00:00:00 2001 From: Jin Cheng Date: Mon, 22 Dec 2025 17:37:28 +0800 Subject: [PATCH 6/6] fix(bt): fixed semaphore deletion condition in UART DMA deinit --- .../bt/porting/transport/driver/uart/hci_driver_uart_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c b/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c index 7bc3cc7c0b..0da3695915 100644 --- a/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c +++ b/components/bt/porting/transport/driver/uart/hci_driver_uart_dma.c @@ -590,7 +590,7 @@ hci_driver_uart_dma_deinit(void) ESP_ERROR_CHECK(uart_driver_delete(s_hci_driver_uart_dma_env.hci_uart_params->hci_uart_port)); hci_driver_uart_dma_memory_deinit(); - if (!s_hci_driver_uart_dma_env.process_sem) { + if (s_hci_driver_uart_dma_env.process_sem) { vSemaphoreDelete(s_hci_driver_uart_dma_env.process_sem); }