mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
fix(bt/bluedroid): added buffer length check for OBEX APIs
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)
|
void bta_av_ca_response(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||||
{
|
{
|
||||||
tOBEX_PARSE_INFO info;
|
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 */
|
/* we always use a final get */
|
||||||
if (p_data->ca_response.opcode == OBEX_OPCODE_GET_FINAL
|
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)))
|
&& (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 *header = NULL;
|
||||||
UINT8 *body_data = NULL;
|
UINT8 *body_data = NULL;
|
||||||
UINT16 body_data_len = 0;
|
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) {
|
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||||
switch (*header)
|
switch (*header)
|
||||||
{
|
{
|
||||||
case OBEX_HEADER_ID_BODY:
|
case OBEX_HEADER_ID_BODY:
|
||||||
/* actually,END_OF_BODY should not in this continue response */
|
/* actually,END_OF_BODY should not in this continue response */
|
||||||
case OBEX_HEADER_ID_END_OF_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;
|
UINT16 seg_len = (hdr_len >= 3) ? (UINT16)(hdr_len - 3) : 0;
|
||||||
if (body_data == NULL) {
|
if (body_data == NULL) {
|
||||||
/* first body header */
|
/* first body header */
|
||||||
@@ -373,7 +378,10 @@ error:
|
|||||||
void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
void bta_av_ca_response_final(tBTA_AV_RCB *p_rcb, tBTA_AV_DATA *p_data)
|
||||||
{
|
{
|
||||||
tOBEX_PARSE_INFO info;
|
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;
|
UINT8 *header = NULL;
|
||||||
if (p_data->ca_response.opcode == OBEX_OPCODE_CONNECT) {
|
if (p_data->ca_response.opcode == OBEX_OPCODE_CONNECT) {
|
||||||
/* we expect a success response code with final bit set */
|
/* 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;
|
p_rcb->cover_art_max_tx = info.max_packet_length;
|
||||||
}
|
}
|
||||||
BOOLEAN cid_found = false;
|
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) {
|
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||||
if (*header == OBEX_HEADER_ID_CONNECTION_ID) {
|
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;
|
cid_found = true;
|
||||||
memcpy((UINT8 *)(&p_rcb->cover_art_cid), header + 1, 4);
|
memcpy((UINT8 *)(&p_rcb->cover_art_cid), header + 1, 4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!cid_found) {
|
if (!cid_found) {
|
||||||
|
osi_free(p_data->ca_response.pkt);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
tBTA_AV_CA_STATUS ca_status;
|
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;
|
UINT16 body_data_len = 0;
|
||||||
/* check response code is success */
|
/* check response code is success */
|
||||||
if (info.response_code == (OBEX_RESPONSE_CODE_OK | OBEX_FINAL_BIT_MASK)) {
|
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) {
|
while((header = OBEX_GetNextHeader(p_data->ca_response.pkt, &info)) != NULL) {
|
||||||
switch (*header)
|
switch (*header)
|
||||||
{
|
{
|
||||||
/* actually, BODY should not in this final response */
|
/* actually, BODY should not in this final response */
|
||||||
case OBEX_HEADER_ID_BODY:
|
case OBEX_HEADER_ID_BODY:
|
||||||
case OBEX_HEADER_ID_END_OF_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;
|
UINT16 seg_len = (hdr_len >= 3) ? (UINT16)(hdr_len - 3) : 0;
|
||||||
if (body_data == NULL) {
|
if (body_data == NULL) {
|
||||||
/* first body header */
|
/* first body header */
|
||||||
|
|||||||
@@ -259,6 +259,6 @@ extern BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt);
|
|||||||
|
|
||||||
extern UINT8 *OBEX_GetNextHeader(BT_HDR *pkt, tOBEX_PARSE_INFO *info);
|
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) */
|
#endif /* #if (OBEX_INCLUDED == TRUE) */
|
||||||
|
|||||||
@@ -674,17 +674,29 @@ UINT16 OBEX_ParseResponse(BT_HDR *pkt, UINT8 opcode, tOBEX_PARSE_INFO *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||||
|
UINT16 len = pkt->len;
|
||||||
|
|
||||||
|
if (len < 1) {
|
||||||
|
return OBEX_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
info->opcode = opcode;
|
info->opcode = opcode;
|
||||||
info->response_code = *p_data;
|
info->response_code = *p_data;
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
case OBEX_OPCODE_CONNECT:
|
case OBEX_OPCODE_CONNECT:
|
||||||
|
if (len < 7) {
|
||||||
|
return OBEX_FAILURE;
|
||||||
|
}
|
||||||
info->obex_version_number = p_data[3];
|
info->obex_version_number = p_data[3];
|
||||||
info->flags = p_data[4];
|
info->flags = p_data[4];
|
||||||
info->max_packet_length = (p_data[5] << 8) + p_data[6];
|
info->max_packet_length = (p_data[5] << 8) + p_data[6];
|
||||||
info->next_header_pos = 7;
|
info->next_header_pos = 7;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (len < 3) {
|
||||||
|
return OBEX_FAILURE;
|
||||||
|
}
|
||||||
info->next_header_pos = 3;
|
info->next_header_pos = 3;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -702,7 +714,7 @@ UINT16 OBEX_ParseResponse(BT_HDR *pkt, UINT8 opcode, tOBEX_PARSE_INFO *info)
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BOOLEAN OBEX_CheckFinalBit(BT_HDR *pkt)
|
BOOLEAN OBEX_CheckFinalBit(BT_HDR *pkt)
|
||||||
{
|
{
|
||||||
if (pkt == NULL) {
|
if (pkt == NULL || pkt->len < 1) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||||
@@ -720,7 +732,7 @@ BOOLEAN OBEX_CheckFinalBit(BT_HDR *pkt)
|
|||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt)
|
BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt)
|
||||||
{
|
{
|
||||||
if (pkt == NULL) {
|
if (pkt == NULL || pkt->len < 1) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||||
@@ -736,15 +748,26 @@ BOOLEAN OBEX_CheckContinueResponse(BT_HDR *pkt)
|
|||||||
** Returns header length
|
** 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;
|
UINT16 header_len = 0;
|
||||||
UINT8 header_id = *header;
|
UINT8 header_id = *header;
|
||||||
|
|
||||||
switch (header_id & OBEX_HEADER_ID_U2B_MASK)
|
switch (header_id & OBEX_HEADER_ID_U2B_MASK)
|
||||||
{
|
{
|
||||||
case OBEX_HEADER_ID_U2B_TYPE1:
|
case OBEX_HEADER_ID_U2B_TYPE1:
|
||||||
case OBEX_HEADER_ID_U2B_TYPE2:
|
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;
|
break;
|
||||||
case OBEX_HEADER_ID_U2B_TYPE3:
|
case OBEX_HEADER_ID_U2B_TYPE3:
|
||||||
header_len = 2;
|
header_len = 2;
|
||||||
@@ -756,6 +779,11 @@ UINT16 OBEX_GetHeaderLength(UINT8 *header)
|
|||||||
/* unreachable */
|
/* unreachable */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header_len > remaining_len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return header_len;
|
return header_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,7 +807,11 @@ UINT8 *OBEX_GetNextHeader(BT_HDR *pkt, tOBEX_PARSE_INFO *info)
|
|||||||
}
|
}
|
||||||
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
UINT8 *p_data = (UINT8 *)(pkt + 1) + pkt->offset;
|
||||||
UINT8 *header = p_data + info->next_header_pos;
|
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;
|
info->next_header_pos += header_len;
|
||||||
return header;
|
return header;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user