mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
fix(ble/bluedroid): Add null/range checks and fix resource handling in BTA layer
- bta_dm_int: fix BTA_SERVICE_ID_TO_SERVICE_MASK undefined behavior (1<<id when id>=32) - bta_gattc_main: add event bounds check before state table lookup - bta_gattc_utils: null checks for remote_bda/p_rcb, fix list_free in clcb_dealloc, bta_to_btif_uuid fixes - bta_gatts_act: fix formatting/indent in send_service_change_indication - bta_gatts_api: validate attr_val/len, add error logs on alloc failure - bta_sys_main: null/range checks in sm_execute, alarm/hash_map error handling in bta_alarm_cb
This commit is contained in:
@@ -45,7 +45,8 @@
|
||||
|
||||
#define BTA_DM_MSG_LEN 50
|
||||
|
||||
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) (1 << (id))
|
||||
/* Use 1ULL to avoid UB: 1 << 32 is undefined when int is 32-bit (C11 §6.5.7) */
|
||||
#define BTA_SERVICE_ID_TO_SERVICE_MASK(id) ((UINT32)(1ULL << (id)))
|
||||
|
||||
/* DM events */
|
||||
enum {
|
||||
|
||||
@@ -108,7 +108,6 @@ const tBTA_GATTC_ACTION bta_gattc_action[] = {
|
||||
#define BTA_GATTC_ACTIONS 1 /* number of actions */
|
||||
#define BTA_GATTC_NEXT_STATE 1 /* position of next state */
|
||||
#define BTA_GATTC_NUM_COLS 2 /* number of columns in state tables */
|
||||
|
||||
/* state table for idle state */
|
||||
static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] = {
|
||||
/* Event Action 1 Next state */
|
||||
@@ -298,6 +297,11 @@ BOOLEAN bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_D
|
||||
|
||||
event &= 0x00FF;
|
||||
|
||||
if (event >= sizeof(bta_gattc_st_idle) / sizeof(bta_gattc_st_idle[0])) {
|
||||
APPL_TRACE_ERROR("bta_gattc_sm_execute: invalid event index %d", event);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* set next state */
|
||||
p_clcb->state = state_table[event][BTA_GATTC_NEXT_STATE];
|
||||
|
||||
|
||||
@@ -125,8 +125,13 @@ tBTA_GATTC_CLCB *bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda
|
||||
tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
|
||||
UINT8 i;
|
||||
|
||||
if (remote_bda == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++) {
|
||||
if (p_clcb->in_use &&
|
||||
p_clcb->p_rcb != NULL &&
|
||||
p_clcb->p_rcb->client_if == client_if &&
|
||||
p_clcb->transport == transport &&
|
||||
bdcmp(p_clcb->bda, remote_bda) == 0) {
|
||||
@@ -244,16 +249,16 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
|
||||
|
||||
if (p_clcb) {
|
||||
p_srcb = p_clcb->p_srcb;
|
||||
if (p_srcb->num_clcb) {
|
||||
if (p_srcb != NULL && p_srcb->num_clcb) {
|
||||
p_srcb->num_clcb --;
|
||||
}
|
||||
|
||||
if (p_clcb->p_rcb->num_clcb) {
|
||||
if (p_clcb->p_rcb != NULL && p_clcb->p_rcb->num_clcb) {
|
||||
p_clcb->p_rcb->num_clcb --;
|
||||
}
|
||||
|
||||
/* if the srcb is no longer needed, reset the state */
|
||||
if ( p_srcb->num_clcb == 0) {
|
||||
if (p_srcb != NULL && p_srcb->num_clcb == 0) {
|
||||
p_srcb->connected = FALSE;
|
||||
p_srcb->state = BTA_GATTC_SERV_IDLE;
|
||||
p_srcb->mtu = 0;
|
||||
@@ -268,13 +273,13 @@ void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
|
||||
#endif
|
||||
}
|
||||
|
||||
if ( p_clcb->p_q_cmd != NULL && !list_contains(p_clcb->p_cmd_list, p_clcb->p_q_cmd)){
|
||||
if (p_clcb->p_q_cmd != NULL &&
|
||||
(p_clcb->p_cmd_list == NULL || !list_contains(p_clcb->p_cmd_list, p_clcb->p_q_cmd))) {
|
||||
osi_free(p_clcb->p_q_cmd);
|
||||
p_clcb->p_q_cmd = NULL;
|
||||
}
|
||||
// don't forget to clear the command queue before dealloc the clcb.
|
||||
list_clear(p_clcb->p_cmd_list);
|
||||
osi_free((void *)p_clcb->p_cmd_list);
|
||||
list_free(p_clcb->p_cmd_list);
|
||||
p_clcb->p_cmd_list = NULL;
|
||||
//osi_free_and_reset((void **)&p_clcb->p_q_cmd);
|
||||
memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
|
||||
@@ -970,6 +975,10 @@ tBTA_GATTC_CLCB *bta_gattc_find_int_conn_clcb(tBTA_GATTC_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTC_CLCB *p_clcb = NULL;
|
||||
|
||||
if (p_msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (p_msg->int_conn.role == HCI_ROLE_SLAVE) {
|
||||
bta_gattc_conn_find_alloc(p_msg->int_conn.remote_bda);
|
||||
}
|
||||
@@ -1005,6 +1014,10 @@ tBTA_GATTC_CLCB *bta_gattc_find_int_disconn_clcb(tBTA_GATTC_DATA *p_msg)
|
||||
{
|
||||
tBTA_GATTC_CLCB *p_clcb = NULL;
|
||||
|
||||
if (p_msg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bta_gattc_conn_dealloc(p_msg->int_conn.remote_bda);
|
||||
if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->int_conn.hdr.layer_specific)) == NULL) {
|
||||
/* connection attempt failed, send connection callback event */
|
||||
@@ -1033,6 +1046,8 @@ void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
|
||||
switch (p_src->len)
|
||||
{
|
||||
case 0:
|
||||
/* Invalid/empty UUID: zero p_dest so callers don't use garbage */
|
||||
memset(p_dest->uu, 0, sizeof(p_dest->uu));
|
||||
break;
|
||||
|
||||
case LEN_UUID_16:
|
||||
@@ -1041,8 +1056,8 @@ void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
|
||||
break;
|
||||
|
||||
case LEN_UUID_32:
|
||||
p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
|
||||
p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
|
||||
p_dest->uu[12] = p_src->uu.uuid32 & 0xff;
|
||||
p_dest->uu[13] = (p_src->uu.uuid32 >> 8) & 0xff;
|
||||
p_dest->uu[14] = (p_src->uu.uuid32 >> 16) & 0xff;
|
||||
p_dest->uu[15] = (p_src->uu.uuid32 >> 24) & 0xff;
|
||||
break;
|
||||
@@ -1054,6 +1069,7 @@ void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
|
||||
|
||||
default:
|
||||
APPL_TRACE_ERROR("%s: Unknown UUID length %d!", __FUNCTION__, p_src->len);
|
||||
memset(p_dest->uu, 0, sizeof(p_dest->uu));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -872,7 +872,7 @@ void bta_gatts_send_service_change_indication (tBTA_GATTS_DATA *p_msg)
|
||||
tBTA_GATTS_RCB *p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_send_service_change.server_if);
|
||||
tBTA_GATTS_SERVICE_CHANGE service_change;
|
||||
tBTA_GATT_STATUS status = BTA_GATT_OK;
|
||||
UINT16 addr[BD_ADDR_LEN] = {0};
|
||||
UINT8 addr[BD_ADDR_LEN] = {0};
|
||||
if(memcmp(p_msg->api_send_service_change.remote_bda, addr, BD_ADDR_LEN) != 0) {
|
||||
BD_ADDR bd_addr;
|
||||
memcpy(bd_addr, p_msg->api_send_service_change.remote_bda, BD_ADDR_LEN);
|
||||
|
||||
@@ -223,6 +223,7 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, const tBT_UUID * p_char_u
|
||||
UINT16 len = 0;
|
||||
if(attr_val != NULL){
|
||||
len = attr_val->attr_len;
|
||||
APPL_TRACE_DEBUG("attr_val->attr_len = %x, attr_max_len = %x\n",attr_val->attr_len, attr_val->attr_max_len);
|
||||
}
|
||||
if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) osi_malloc(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL) {
|
||||
memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
|
||||
@@ -234,15 +235,22 @@ void BTA_GATTS_AddCharacteristic (UINT16 service_id, const tBT_UUID * p_char_u
|
||||
if(control !=NULL){
|
||||
p_buf->control.auto_rsp = control->auto_rsp;
|
||||
}
|
||||
if(attr_val != NULL){
|
||||
APPL_TRACE_DEBUG("!!!!!!attr_val->attr_len = %x\n",attr_val->attr_len);
|
||||
APPL_TRACE_DEBUG("!!!!!!!attr_val->attr_max_len = %x\n",attr_val->attr_max_len);
|
||||
|
||||
if(attr_val != NULL && len){
|
||||
p_buf->attr_val.attr_len = attr_val->attr_len;
|
||||
p_buf->attr_val.attr_max_len = attr_val->attr_max_len;
|
||||
p_buf->attr_val.attr_val = (uint8_t *)osi_malloc(len);
|
||||
if(p_buf->attr_val.attr_val != NULL){
|
||||
memcpy(p_buf->attr_val.attr_val, attr_val->attr_val, len);
|
||||
} else {
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
p_buf->attr_val.attr_max_len = 0;
|
||||
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
|
||||
}
|
||||
} else {
|
||||
p_buf->attr_val.attr_len = 0;
|
||||
p_buf->attr_val.attr_max_len = 0;
|
||||
p_buf->attr_val.attr_val = NULL;
|
||||
}
|
||||
|
||||
if (p_char_uuid) {
|
||||
@@ -499,6 +507,9 @@ void BTA_SetAttributeValue(UINT16 attr_handle, UINT16 length, UINT8 *value)
|
||||
if(value != NULL){
|
||||
if((p_buf->value = (UINT8 *)osi_malloc(length)) != NULL){
|
||||
memcpy(p_buf->value, value, length);
|
||||
} else {
|
||||
p_buf->length = 0;
|
||||
APPL_TRACE_ERROR("Allocate fail for %s\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -103,6 +103,7 @@ enum {
|
||||
#define BTA_SYS_ACTIONS 2 /* number of actions */
|
||||
#define BTA_SYS_NEXT_STATE 2 /* position of next state */
|
||||
#define BTA_SYS_NUM_COLS 3 /* number of columns in state tables */
|
||||
#define BTA_SYS_NUM_STATES 4 /* OFF, STARTING, ON, STOPPING */
|
||||
|
||||
|
||||
/* state table for OFF state */
|
||||
@@ -213,22 +214,39 @@ BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
|
||||
BOOLEAN freebuf = TRUE;
|
||||
tBTA_SYS_ST_TBL state_table;
|
||||
UINT8 action;
|
||||
UINT8 evt_idx;
|
||||
int i;
|
||||
|
||||
if (p_msg == NULL) {
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
evt_idx = p_msg->event & 0x00ff;
|
||||
if (evt_idx >= BTA_SYS_NUM_ACTIONS) {
|
||||
APPL_TRACE_ERROR("bta_sys_sm_execute: event 0x%x out of range (evt_idx=%u)", p_msg->event, evt_idx);
|
||||
return freebuf;
|
||||
}
|
||||
if (bta_sys_cb.state >= BTA_SYS_NUM_STATES) {
|
||||
APPL_TRACE_ERROR("bta_sys_sm_execute: invalid state %u", bta_sys_cb.state);
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
APPL_TRACE_EVENT("bta_sys_sm_execute state:%d, event:0x%x\n", bta_sys_cb.state, p_msg->event);
|
||||
|
||||
/* look up the state table for the current state */
|
||||
state_table = bta_sys_st_tbl[bta_sys_cb.state];
|
||||
/* update state */
|
||||
bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
|
||||
bta_sys_cb.state = state_table[evt_idx][BTA_SYS_NEXT_STATE];
|
||||
|
||||
/* execute action functions */
|
||||
for (i = 0; i < BTA_SYS_ACTIONS; i++) {
|
||||
if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE) {
|
||||
(*bta_sys_action[action])( (tBTA_SYS_HW_MSG *) p_msg);
|
||||
} else {
|
||||
action = state_table[evt_idx][i];
|
||||
if (action == BTA_SYS_IGNORE) {
|
||||
break;
|
||||
}
|
||||
if (action < BTA_SYS_NUM_ACTIONS) {
|
||||
(*bta_sys_action[action])( (tBTA_SYS_HW_MSG *) p_msg);
|
||||
}
|
||||
}
|
||||
return freebuf;
|
||||
|
||||
@@ -598,16 +616,29 @@ void bta_alarm_cb(void *data)
|
||||
|
||||
void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms)
|
||||
{
|
||||
osi_alarm_t *alarm = NULL;
|
||||
|
||||
assert(p_tle != NULL);
|
||||
|
||||
// Get the alarm for this p_tle.
|
||||
osi_mutex_lock(&bta_alarm_lock, OSI_MUTEX_MAX_TIMEOUT);
|
||||
if (!hash_map_has_key(bta_alarm_hash_map, p_tle)) {
|
||||
hash_map_set(bta_alarm_hash_map, p_tle, osi_alarm_new("bta_sys", bta_alarm_cb, p_tle, 0));
|
||||
alarm = osi_alarm_new("bta_sys", bta_alarm_cb, p_tle, 0);
|
||||
if (alarm == NULL) {
|
||||
APPL_TRACE_ERROR("%s unable to create new alarm.", __func__);
|
||||
osi_mutex_unlock(&bta_alarm_lock);
|
||||
return;
|
||||
}
|
||||
if (!hash_map_set(bta_alarm_hash_map, p_tle, alarm)) {
|
||||
APPL_TRACE_ERROR("%s unable to set alarm in map.", __func__);
|
||||
osi_alarm_free(alarm);
|
||||
osi_mutex_unlock(&bta_alarm_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
osi_mutex_unlock(&bta_alarm_lock);
|
||||
|
||||
osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle);
|
||||
alarm = hash_map_get(bta_alarm_hash_map, p_tle);
|
||||
if (alarm == NULL) {
|
||||
APPL_TRACE_ERROR("%s unable to create alarm.", __func__);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user