mirror of
https://github.com/espressif/esp-idf.git
synced 2026-07-19 17:33:19 +03:00
Merge branch 'bugfix/bbp_isses_v5.5' into 'release/v5.5'
Bugfix/bbp isses v5.5 See merge request espressif/esp-idf!49625
This commit is contained in:
@@ -314,7 +314,10 @@ error:
|
||||
void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
tOBEX_PARSE_INFO info;
|
||||
OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info);
|
||||
if (OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info) != OBEX_SUCCESS) {
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
goto error;
|
||||
}
|
||||
/* we always use a final get */
|
||||
if (p_data->ca_response.opcode == OBEX_OPCODE_GET_FINAL
|
||||
&& (info.response_code == OBEX_RESPONSE_CODE_CONTINUE || info.response_code == (OBEX_RESPONSE_CODE_CONTINUE | OBEX_FINAL_BIT_MASK)))
|
||||
@@ -322,13 +325,15 @@ void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
UINT8 *header = NULL;
|
||||
UINT8 *body_data = NULL;
|
||||
UINT16 body_data_len = 0;
|
||||
UINT8 *pkt_data = (UINT8 *)(p_data->ca_response.pkt + 1) + p_data->ca_response.pkt->offset;
|
||||
UINT8 *pkt_end = pkt_data + p_data->ca_response.pkt->len;
|
||||
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||
switch (*header)
|
||||
{
|
||||
case OBEX_HEADER_ID_BODY:
|
||||
/* actually,END_OF_BODY should not in this continue response */
|
||||
case OBEX_HEADER_ID_END_OF_BODY: {
|
||||
UINT16 hdr_len = OBEX_GetHeaderLength(header);
|
||||
UINT16 hdr_len = OBEX_GetHeaderLength(header, pkt_end);
|
||||
UINT16 seg_len = (hdr_len >= 3) ? (UINT16)(hdr_len - 3) : 0;
|
||||
if (body_data == NULL) {
|
||||
/* first body header */
|
||||
@@ -373,7 +378,10 @@ error:
|
||||
void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
{
|
||||
tOBEX_PARSE_INFO info;
|
||||
OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info);
|
||||
if (OBEX_ParseResponse(p_data->ca_response.pkt, p_data->ca_response.opcode, &info) != OBEX_SUCCESS) {
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
goto error;
|
||||
}
|
||||
UINT8 *header = NULL;
|
||||
if (p_data->ca_response.opcode == OBEX_OPCODE_CONNECT) {
|
||||
/* we expect a success response code with final bit set */
|
||||
@@ -385,14 +393,21 @@ void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
p_rcb->cover_art_max_tx = info.max_packet_length;
|
||||
}
|
||||
BOOLEAN cid_found = false;
|
||||
UINT8 *pkt_data = (UINT8 *)(p_data->ca_response.pkt + 1) + p_data->ca_response.pkt->offset;
|
||||
UINT8 *pkt_end = pkt_data + p_data->ca_response.pkt->len;
|
||||
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||
if (*header == OBEX_HEADER_ID_CONNECTION_ID) {
|
||||
if (OBEX_GetHeaderLength(header, pkt_end) != 5) {
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
goto error;
|
||||
}
|
||||
cid_found = true;
|
||||
memcpy((UINT8 *)(&p_rcb->cover_art_cid), header + 1, 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cid_found) {
|
||||
osi_free(p_data->ca_response.pkt);
|
||||
goto error;
|
||||
}
|
||||
tBTA_AV_CA_STATUS ca_status;
|
||||
@@ -412,13 +427,15 @@ void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||
UINT16 body_data_len = 0;
|
||||
/* check response code is success */
|
||||
if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) {
|
||||
UINT8 *pkt_data = (UINT8 *)(p_data->ca_response.pkt + 1) + p_data->ca_response.pkt->offset;
|
||||
UINT8 *pkt_end = pkt_data + p_data->ca_response.pkt->len;
|
||||
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||
switch (*header)
|
||||
{
|
||||
/* actually, BODY should not in this final response */
|
||||
case OBEX_HEADER_ID_BODY:
|
||||
case OBEX_HEADER_ID_END_OF_BODY: {
|
||||
UINT16 hdr_len = OBEX_GetHeaderLength(header);
|
||||
UINT16 hdr_len = OBEX_GetHeaderLength(header, pkt_end);
|
||||
UINT16 seg_len = (hdr_len >= 3) ? (UINT16)(hdr_len - 3) : 0;
|
||||
if (body_data == NULL) {
|
||||
/* first body header */
|
||||
|
||||
@@ -463,7 +463,9 @@ void bta_pba_client_response(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p
|
||||
tOBEX_PARSE_INFO info;
|
||||
tBTA_PBA_CLIENT_ERR reason = BTA_PBA_CLIENT_GOEP_ERROR;
|
||||
|
||||
OBEX_ParseResponse(p_data->goep_response.pkt, p_data->goep_response.opcode, &info);
|
||||
if (OBEX_ParseResponse(p_data->goep_response.pkt, p_data->goep_response.opcode, &info) != OBEX_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
if (p_data->goep_response.opcode == OBEX_OPCODE_GET_FINAL &&
|
||||
(info.response_code == OBEX_RESPONSE_CODE_CONTINUE || info.response_code == (OBEX_RESPONSE_CODE_CONTINUE | OBEX_FINAL_BIT_MASK))) {
|
||||
UINT8 *header = NULL;
|
||||
@@ -471,13 +473,15 @@ void bta_pba_client_response(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p
|
||||
UINT16 body_data_len = 0;
|
||||
UINT8 *app_param = NULL;
|
||||
UINT16 app_param_len = 0;
|
||||
UINT8 *pkt_data = (UINT8 *)(p_data->goep_response.pkt + 1) + p_data->goep_response.pkt->offset;
|
||||
UINT8 *pkt_end = pkt_data + p_data->goep_response.pkt->len;
|
||||
while((header = OBEX_GetNextHeader(p_data->goep_response.pkt, &info)) != NULL) {
|
||||
switch (*header)
|
||||
{
|
||||
case OBEX_HEADER_ID_BODY:
|
||||
case OBEX_HEADER_ID_END_OF_BODY:
|
||||
{
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header);
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header, pkt_end);
|
||||
if (hi_len < 3) {
|
||||
reason = BTA_PBA_CLIENT_BAD_REQUEST;
|
||||
goto error;
|
||||
@@ -497,7 +501,7 @@ void bta_pba_client_response(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_DATA *p
|
||||
}
|
||||
case OBEX_HEADER_ID_APP_PARAM:
|
||||
{
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header);
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header, pkt_end);
|
||||
if (hi_len < 3) {
|
||||
reason = BTA_PBA_CLIENT_BAD_REQUEST;
|
||||
goto error;
|
||||
@@ -544,7 +548,9 @@ void bta_pba_client_response_final(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_D
|
||||
UINT8 *header = NULL;
|
||||
tBTA_PBA_CLIENT_ERR reason = BTA_PBA_CLIENT_FAIL;
|
||||
|
||||
OBEX_ParseResponse(p_data->goep_response.pkt, p_data->goep_response.opcode, &info);
|
||||
if (OBEX_ParseResponse(p_data->goep_response.pkt, p_data->goep_response.opcode, &info) != OBEX_SUCCESS) {
|
||||
goto error;
|
||||
}
|
||||
if (p_data->goep_response.opcode == OBEX_OPCODE_CONNECT) {
|
||||
if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) {
|
||||
/* obex connect success */
|
||||
@@ -555,8 +561,13 @@ void bta_pba_client_response_final(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_D
|
||||
p_ccb->max_tx = info.max_packet_length;
|
||||
}
|
||||
BOOLEAN cid_found = false;
|
||||
UINT8 *pkt_data = (UINT8 *)(p_data->goep_response.pkt + 1) + p_data->goep_response.pkt->offset;
|
||||
UINT8 *pkt_end = pkt_data + p_data->goep_response.pkt->len;
|
||||
while((header = OBEX_GetNextHeader(p_data->goep_response.pkt, &info)) != NULL) {
|
||||
if (*header == OBEX_HEADER_ID_CONNECTION_ID) {
|
||||
if (OBEX_GetHeaderLength(header, pkt_end) != 5) {
|
||||
goto error;
|
||||
}
|
||||
cid_found = true;
|
||||
memcpy((UINT8 *)(&p_ccb->goep_cid), header + 1, 4);
|
||||
break;
|
||||
@@ -600,6 +611,8 @@ void bta_pba_client_response_final(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_D
|
||||
UINT16 body_data_len = 0;
|
||||
UINT8 *app_param = NULL;
|
||||
UINT16 app_param_len = 0;
|
||||
UINT8 *pkt_data = (UINT8 *)(p_data->goep_response.pkt + 1) + p_data->goep_response.pkt->offset;
|
||||
UINT8 *pkt_end = pkt_data + p_data->goep_response.pkt->len;
|
||||
while((header = OBEX_GetNextHeader(p_data->goep_response.pkt, &info)) != NULL) {
|
||||
switch (*header)
|
||||
{
|
||||
@@ -607,7 +620,7 @@ void bta_pba_client_response_final(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_D
|
||||
case OBEX_HEADER_ID_BODY:
|
||||
case OBEX_HEADER_ID_END_OF_BODY:
|
||||
{
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header);
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header, pkt_end);
|
||||
if (hi_len < 3) {
|
||||
reason = BTA_PBA_CLIENT_BAD_REQUEST;
|
||||
goto error;
|
||||
@@ -627,7 +640,7 @@ void bta_pba_client_response_final(tBTA_PBA_CLIENT_CCB *p_ccb, tBTA_PBA_CLIENT_D
|
||||
}
|
||||
case OBEX_HEADER_ID_APP_PARAM:
|
||||
{
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header);
|
||||
UINT16 hi_len = OBEX_GetHeaderLength(header, pkt_end);
|
||||
if (hi_len < 3) {
|
||||
reason = BTA_PBA_CLIENT_BAD_REQUEST;
|
||||
goto error;
|
||||
|
||||
@@ -507,6 +507,11 @@ static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg)
|
||||
osi_free(p_msg);
|
||||
return;
|
||||
}
|
||||
if (p_msg->len < 1) {
|
||||
HIDD_TRACE_WARNING ("HID-Device Rcvd Empty L2CAP data");
|
||||
osi_free(p_msg);
|
||||
return;
|
||||
}
|
||||
msg_type = HID_GET_TRANS_FROM_HDR(*p_data);
|
||||
param = HID_GET_PARAM_FROM_HDR(*p_data);
|
||||
if (msg_type == HID_TRANS_DATA && cid == p_hcon->intr_cid) {
|
||||
|
||||
@@ -766,6 +766,11 @@ static void hidh_l2cif_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg)
|
||||
return;
|
||||
}
|
||||
|
||||
if (p_msg->len < 1) {
|
||||
HIDH_TRACE_WARNING ("HID-Host Rcvd Empty L2CAP data");
|
||||
osi_free (p_msg);
|
||||
return;
|
||||
}
|
||||
|
||||
ttype = HID_GET_TRANS_FROM_HDR(*p_data);
|
||||
param = HID_GET_PARAM_FROM_HDR(*p_data);
|
||||
|
||||
@@ -266,6 +266,6 @@ extern BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt);
|
||||
|
||||
extern UINT8 *OBEX_GetNextHeader(BT_HDR *pkt, tOBEX_PARSE_INFO *info);
|
||||
|
||||
extern UINT16 OBEX_GetHeaderLength(UINT8 *header);
|
||||
extern UINT16 OBEX_GetHeaderLength(UINT8 *header, UINT8 *pkt_end);
|
||||
|
||||
#endif /* #if (OBEX_INCLUDED == TRUE) */
|
||||
|
||||
@@ -352,7 +352,7 @@ void l2c_rcv_acl_data (BT_HDR *p_msg)
|
||||
#if (CLASSIC_BT_INCLUDED == TRUE)
|
||||
static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
{
|
||||
UINT8 *p_pkt_end, *p_next_cmd, *p_cfg_end, *p_cfg_start;
|
||||
UINT8 *p_pkt_end, *p_next_cmd, *p_cfg_end, *p_cfg_start, *p_cfg_opt_end;
|
||||
UINT8 cmd_code, cfg_code, cfg_len, id;
|
||||
tL2C_CONN_INFO con_info;
|
||||
tL2CAP_CFG_INFO cfg_info;
|
||||
@@ -526,6 +526,10 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CMD_CONFIG_REQ:
|
||||
if (cmd_len < L2CAP_CONFIG_REQ_LEN) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - cfg req too short, cmd_len: %d", cmd_len);
|
||||
break;
|
||||
}
|
||||
p_cfg_end = p + cmd_len;
|
||||
cfg_rej = FALSE;
|
||||
cfg_rej_len = 0;
|
||||
@@ -539,21 +543,47 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
cfg_info.fcr_present = cfg_info.fcs_present = FALSE;
|
||||
|
||||
while (p < p_cfg_end) {
|
||||
if ((p_cfg_end - p) < L2CAP_CFG_OPTION_OVERHEAD) {
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
STREAM_TO_UINT8 (cfg_code, p);
|
||||
STREAM_TO_UINT8 (cfg_len, p);
|
||||
if (cfg_len > (p_cfg_end - p)) {
|
||||
p = p_cfg_end;
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
p_cfg_opt_end = p + cfg_len;
|
||||
|
||||
switch (cfg_code & 0x7F) {
|
||||
case L2CAP_CFG_TYPE_MTU:
|
||||
if (cfg_len != L2CAP_CFG_MTU_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
cfg_info.mtu_present = TRUE;
|
||||
STREAM_TO_UINT16 (cfg_info.mtu, p);
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_FLUSH_TOUT:
|
||||
if (cfg_len != L2CAP_CFG_FLUSH_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
cfg_info.flush_to_present = TRUE;
|
||||
STREAM_TO_UINT16 (cfg_info.flush_to, p);
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_QOS:
|
||||
if (cfg_len != L2CAP_CFG_QOS_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
cfg_info.qos_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.qos.qos_flags, p);
|
||||
STREAM_TO_UINT8 (cfg_info.qos.service_type, p);
|
||||
@@ -565,6 +595,11 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_FCR:
|
||||
if (cfg_len != L2CAP_CFG_FCR_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
cfg_info.fcr_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.fcr.mode, p);
|
||||
STREAM_TO_UINT8 (cfg_info.fcr.tx_win_sz, p);
|
||||
@@ -575,11 +610,21 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_FCS:
|
||||
if (cfg_len != L2CAP_CFG_FCS_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
cfg_info.fcs_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.fcs, p);
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_EXT_FLOW:
|
||||
if (cfg_len != L2CAP_CFG_EXT_FLOW_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
cfg_rej = TRUE;
|
||||
break;
|
||||
}
|
||||
cfg_info.ext_flow_spec_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.ext_flow_spec.id, p);
|
||||
STREAM_TO_UINT8 (cfg_info.ext_flow_spec.stype, p);
|
||||
@@ -590,17 +635,9 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
default:
|
||||
/* sanity check option length */
|
||||
if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= cmd_len) {
|
||||
p += cfg_len;
|
||||
if ((cfg_code & 0x80) == 0) {
|
||||
cfg_rej_len += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
|
||||
cfg_rej = TRUE;
|
||||
}
|
||||
}
|
||||
/* bad length; force loop exit */
|
||||
else {
|
||||
p = p_cfg_end;
|
||||
p = p_cfg_opt_end;
|
||||
if ((cfg_code & 0x80) == 0) {
|
||||
cfg_rej_len += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
|
||||
cfg_rej = TRUE;
|
||||
}
|
||||
break;
|
||||
@@ -621,6 +658,10 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CMD_CONFIG_RSP:
|
||||
if (cmd_len < L2CAP_CONFIG_RSP_LEN) {
|
||||
L2CAP_TRACE_WARNING ("L2CAP - cfg rsp too short, cmd_len: %d", cmd_len);
|
||||
break;
|
||||
}
|
||||
p_cfg_end = p + cmd_len;
|
||||
STREAM_TO_UINT16 (lcid, p);
|
||||
STREAM_TO_UINT16 (cfg_info.flags, p);
|
||||
@@ -630,21 +671,42 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
cfg_info.fcr_present = cfg_info.fcs_present = FALSE;
|
||||
|
||||
while (p < p_cfg_end) {
|
||||
if ((p_cfg_end - p) < L2CAP_CFG_OPTION_OVERHEAD) {
|
||||
break;
|
||||
}
|
||||
|
||||
STREAM_TO_UINT8 (cfg_code, p);
|
||||
STREAM_TO_UINT8 (cfg_len, p);
|
||||
if (cfg_len > (p_cfg_end - p)) {
|
||||
p = p_cfg_end;
|
||||
break;
|
||||
}
|
||||
p_cfg_opt_end = p + cfg_len;
|
||||
|
||||
switch (cfg_code & 0x7F) {
|
||||
case L2CAP_CFG_TYPE_MTU:
|
||||
if (cfg_len != L2CAP_CFG_MTU_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
break;
|
||||
}
|
||||
cfg_info.mtu_present = TRUE;
|
||||
STREAM_TO_UINT16 (cfg_info.mtu, p);
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_FLUSH_TOUT:
|
||||
if (cfg_len != L2CAP_CFG_FLUSH_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
break;
|
||||
}
|
||||
cfg_info.flush_to_present = TRUE;
|
||||
STREAM_TO_UINT16 (cfg_info.flush_to, p);
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_QOS:
|
||||
if (cfg_len != L2CAP_CFG_QOS_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
break;
|
||||
}
|
||||
cfg_info.qos_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.qos.qos_flags, p);
|
||||
STREAM_TO_UINT8 (cfg_info.qos.service_type, p);
|
||||
@@ -656,6 +718,10 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_FCR:
|
||||
if (cfg_len != L2CAP_CFG_FCR_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
break;
|
||||
}
|
||||
cfg_info.fcr_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.fcr.mode, p);
|
||||
STREAM_TO_UINT8 (cfg_info.fcr.tx_win_sz, p);
|
||||
@@ -666,11 +732,19 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_FCS:
|
||||
if (cfg_len != L2CAP_CFG_FCS_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
break;
|
||||
}
|
||||
cfg_info.fcs_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.fcs, p);
|
||||
break;
|
||||
|
||||
case L2CAP_CFG_TYPE_EXT_FLOW:
|
||||
if (cfg_len != L2CAP_CFG_EXT_FLOW_OPTION_LEN) {
|
||||
p = p_cfg_end;
|
||||
break;
|
||||
}
|
||||
cfg_info.ext_flow_spec_present = TRUE;
|
||||
STREAM_TO_UINT8 (cfg_info.ext_flow_spec.id, p);
|
||||
STREAM_TO_UINT8 (cfg_info.ext_flow_spec.stype, p);
|
||||
@@ -679,6 +753,9 @@ static void process_l2cap_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
|
||||
STREAM_TO_UINT32 (cfg_info.ext_flow_spec.access_latency, p);
|
||||
STREAM_TO_UINT32 (cfg_info.ext_flow_spec.flush_timeout, p);
|
||||
break;
|
||||
default:
|
||||
p = p_cfg_opt_end;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -879,7 +879,7 @@ void l2cu_send_peer_config_rsp (tL2C_CCB *p_ccb, tL2CAP_CFG_INFO *p_cfg)
|
||||
void l2cu_send_peer_config_rej (tL2C_CCB *p_ccb, UINT8 *p_data, UINT16 data_len, UINT16 rej_len)
|
||||
{
|
||||
BT_HDR *p_buf;
|
||||
UINT16 len, cfg_len, buf_space, len1;
|
||||
UINT16 len, cfg_len, buf_space, len1, opt_len;
|
||||
UINT8 *p, *p_hci_len, *p_data_end;
|
||||
UINT8 cfg_code;
|
||||
|
||||
@@ -936,38 +936,42 @@ void l2cu_send_peer_config_rej (tL2C_CCB *p_ccb, UINT8 *p_data, UINT16 data_len,
|
||||
/* Now, put the rejected options */
|
||||
p_data_end = p_data + data_len;
|
||||
while (p_data < p_data_end) {
|
||||
if ((p_data_end - p_data) < L2CAP_CFG_OPTION_OVERHEAD) {
|
||||
break;
|
||||
}
|
||||
cfg_code = *p_data;
|
||||
cfg_len = *(p_data + 1);
|
||||
opt_len = cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
|
||||
if (opt_len > (UINT16)(p_data_end - p_data)) {
|
||||
p_data = p_data_end;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (cfg_code & 0x7F) {
|
||||
/* skip known options */
|
||||
case L2CAP_CFG_TYPE_MTU:
|
||||
case L2CAP_CFG_TYPE_FLUSH_TOUT:
|
||||
case L2CAP_CFG_TYPE_QOS:
|
||||
p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
|
||||
case L2CAP_CFG_TYPE_FCR:
|
||||
case L2CAP_CFG_TYPE_FCS:
|
||||
case L2CAP_CFG_TYPE_EXT_FLOW:
|
||||
p_data += opt_len;
|
||||
break;
|
||||
|
||||
/* unknown options; copy into rsp if not hints */
|
||||
default:
|
||||
/* sanity check option length */
|
||||
if ((cfg_len + L2CAP_CFG_OPTION_OVERHEAD) <= data_len) {
|
||||
if ((cfg_code & 0x80) == 0) {
|
||||
if (buf_space >= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD)) {
|
||||
memcpy(p, p_data, cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
|
||||
p += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
|
||||
buf_space -= (cfg_len + L2CAP_CFG_OPTION_OVERHEAD);
|
||||
} else {
|
||||
L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
|
||||
p_data = p_data_end; /* force loop exit */
|
||||
break;
|
||||
}
|
||||
if ((cfg_code & 0x80) == 0) {
|
||||
if (buf_space >= opt_len) {
|
||||
memcpy(p, p_data, opt_len);
|
||||
p += opt_len;
|
||||
buf_space -= opt_len;
|
||||
} else {
|
||||
L2CAP_TRACE_WARNING("L2CAP - cfg_rej exceeds allocated buffer");
|
||||
p_data = p_data_end; /* force loop exit */
|
||||
break;
|
||||
}
|
||||
p_data += cfg_len + L2CAP_CFG_OPTION_OVERHEAD;
|
||||
}
|
||||
/* bad length; force loop exit */
|
||||
else {
|
||||
p_data = p_data_end;
|
||||
}
|
||||
p_data += opt_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -680,17 +680,29 @@ UINT16 OBEX_ParseResponse(BT_HDR *pkt, UINT8 opcode, tOBEX_PARSE_INFO *info)
|
||||
}
|
||||
|
||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||
UINT16 len = pkt->len;
|
||||
|
||||
if (len < 1) {
|
||||
return OBEX_FAILURE;
|
||||
}
|
||||
|
||||
info->opcode = opcode;
|
||||
info->response_code = *p_data;
|
||||
switch (opcode)
|
||||
{
|
||||
case OBEX_OPCODE_CONNECT:
|
||||
if (len < 7) {
|
||||
return OBEX_FAILURE;
|
||||
}
|
||||
info->obex_version_number = p_data[3];
|
||||
info->flags = p_data[4];
|
||||
info->max_packet_length = (p_data[5] << 8) + p_data[6];
|
||||
info->next_header_pos = 7;
|
||||
break;
|
||||
default:
|
||||
if (len < 3) {
|
||||
return OBEX_FAILURE;
|
||||
}
|
||||
info->next_header_pos = 3;
|
||||
break;
|
||||
}
|
||||
@@ -708,7 +720,7 @@ UINT16 OBEX_ParseResponse(BT_HDR *pkt, UINT8 opcode, tOBEX_PARSE_INFO *info)
|
||||
*******************************************************************************/
|
||||
BOOLEAN OBEX_CheckFinalBit(BT_HDR *pkt)
|
||||
{
|
||||
if (pkt == NULL) {
|
||||
if (pkt == NULL || pkt->len < 1) {
|
||||
return FALSE;
|
||||
}
|
||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||
@@ -726,7 +738,7 @@ BOOLEAN OBEX_CheckFinalBit(BT_HDR *pkt)
|
||||
*******************************************************************************/
|
||||
BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt)
|
||||
{
|
||||
if (pkt == NULL) {
|
||||
if (pkt == NULL || pkt->len < 1) {
|
||||
return FALSE;
|
||||
}
|
||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||
@@ -742,15 +754,26 @@ BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt)
|
||||
** Returns header length
|
||||
**
|
||||
*******************************************************************************/
|
||||
UINT16 OBEX_GetHeaderLength(UINT8 *header)
|
||||
UINT16 OBEX_GetHeaderLength(UINT8 *header, UINT8 *pkt_end)
|
||||
{
|
||||
if (header == NULL || pkt_end == NULL || header >= pkt_end) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
UINT16 remaining_len = (UINT16)(pkt_end - header);
|
||||
UINT16 header_len = 0;
|
||||
UINT8 header_id = *header;
|
||||
|
||||
switch (header_id & OBEX_HEADER_ID_U2B_MASK)
|
||||
{
|
||||
case OBEX_HEADER_ID_U2B_TYPE1:
|
||||
case OBEX_HEADER_ID_U2B_TYPE2:
|
||||
header_len = (header[1] << 8) + header[2];
|
||||
if (remaining_len >= 3) {
|
||||
header_len = (header[1] << 8) + header[2];
|
||||
}
|
||||
if (header_len < 3) {
|
||||
header_len = 0;
|
||||
}
|
||||
break;
|
||||
case OBEX_HEADER_ID_U2B_TYPE3:
|
||||
header_len = 2;
|
||||
@@ -762,6 +785,11 @@ UINT16 OBEX_GetHeaderLength(UINT8 *header)
|
||||
/* unreachable */
|
||||
break;
|
||||
}
|
||||
|
||||
if (header_len > remaining_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return header_len;
|
||||
}
|
||||
|
||||
@@ -785,7 +813,11 @@ UINT8 *OBEX_GetNextHeader(BT_HDR *pkt, tOBEX_PARSE_INFO *info)
|
||||
}
|
||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||
UINT8 *header = p_data + info->next_header_pos;
|
||||
UINT16 header_len = OBEX_GetHeaderLength(header);
|
||||
UINT8 *pkt_end = p_data + pkt->len;
|
||||
UINT16 header_len = OBEX_GetHeaderLength(header, pkt_end);
|
||||
if (header_len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
info->next_header_pos += header_len;
|
||||
return header;
|
||||
}
|
||||
|
||||
@@ -2315,11 +2315,8 @@ BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb)
|
||||
SMP_TRACE_ERROR("%s failed", __func__);
|
||||
} else {
|
||||
UINT8 link_key_type;
|
||||
if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
|
||||
/* Secure Connections Only Mode */
|
||||
link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
|
||||
} else if (controller_get_interface()->supports_secure_connections()) {
|
||||
/* both transports are SC capable */
|
||||
if ((btm_cb.security_mode == BTM_SEC_MODE_SC) ||
|
||||
(controller_get_interface()->supports_secure_connections())) {
|
||||
if (p_cb->sec_level == SMP_SEC_AUTHENTICATED) {
|
||||
link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
|
||||
} else {
|
||||
|
||||
@@ -335,13 +335,15 @@ static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Validate command length to prevent out-of-bounds read in handler functions */
|
||||
if (p_buf->len != smp_cmd_size_per_spec[cmd]) {
|
||||
SMP_TRACE_WARNING( "Ignore received command 0x%02x with invalid length %d", cmd, p_buf->len);
|
||||
osi_free(p_buf);
|
||||
return;
|
||||
}
|
||||
|
||||
/* reject the pairing request if there is an on-going SMP pairing */
|
||||
if (SMP_OPCODE_PAIRING_REQ == cmd) {
|
||||
if (p_buf->len != smp_cmd_size_per_spec[cmd]) {
|
||||
SMP_TRACE_WARNING( "Ignore received command 0x%02x with invalid length %d", cmd, p_buf->len);
|
||||
osi_free(p_buf);
|
||||
return;
|
||||
}
|
||||
if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE)) {
|
||||
p_cb->role = HCI_ROLE_SLAVE;
|
||||
p_cb->smp_over_br = TRUE;
|
||||
|
||||
Reference in New Issue
Block a user