fix(bt/bluedroid): fixed heap corruption when deinit SPP during SDP discovery

bta_jv_disable() reset the control block and let BTA_JvFree() release
p_sdp_db/p_sdp_raw_data while an SDP service search could still be in
progress. Late SDP responses were then parsed into the freed discovery
database and corrupted the heap, so the crash surfaced much later in an
unrelated malloc(), inside TLSF remove_free_block().

Cancel the search first. SDP_CancelServiceSearch() moves the connection
control block to SDP_DISC_WAIT_CANCEL, and sdp_disc_server_rsp() matches
none of its PDU cases in that state, so a late response is rejected
instead of being written into the database.

Reachable from both esp_spp_deinit() and esp_bt_l2cap_deinit(), e.g. when
an application deinitializes SPP before ESP_SPP_DISCOVERY_COMP_EVT
arrives.
This commit is contained in:
xiongweichao
2026-09-22 14:14:34 +08:00
parent 1a70765bb3
commit 2b2b88a33c
@@ -754,6 +754,15 @@ void bta_jv_disable (tBTA_JV_MSG *p_data)
tBTA_JV_STATUS evt_data;
evt_data = BTA_JV_SUCCESS;
/* An SDP search still in progress keeps writing into p_bta_jv_cfg->p_sdp_db,
* which BTA_JvFree() releases once BTA_JV_DISABLE_EVT is handled. Cancel it
* first: the connection control block then rejects any late response instead
* of parsing it into freed memory. */
if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) {
APPL_TRACE_WARNING("%s: SDP discovery active, cancelling it", __func__);
SDP_CancelServiceSearch(p_bta_jv_cfg->p_sdp_db);
}
// clear all the pm_cb slots
for (int i = 0; i < BTA_JV_PM_MAX_NUM; i++) {
if (bta_jv_cb.pm_cb[i].state != BTA_JV_PM_FREE_ST) {