/* Start inactivity timer */
alarm_set_on_queue(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
sdp_conn_timer_timeout, p_ccb, btu_general_alarm_queue);
+ if (p_req + sizeof(pdu_id) + sizeof(trans_num) > p_req_end) {
+ android_errorWriteLog(0x534e4554, "69384124");
+ trans_num = 0;
+ sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
+ SDP_TEXT_BAD_HEADER);
+ }
/* The first byte in the message is the pdu type */
pdu_id = *p_req++;
/* Extract the transaction number and parameter length */
BE_STREAM_TO_UINT16 (trans_num, p_req);
+
+ if (p_req + sizeof(param_len) > p_req_end) {
+ android_errorWriteLog(0x534e4554, "69384124");
+ sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX,
+ SDP_TEXT_BAD_HEADER);
+ }
+
BE_STREAM_TO_UINT16 (param_len, p_req);
if ((p_req + param_len) != p_req_end)
}
/* Get the max replies we can send. Cap it at our max anyways. */
+ if (p_req + sizeof(max_replies) + sizeof(uint8_t) > p_req_end) {
+ android_errorWriteLog(0x534e4554, "69384124");
+ sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_MAX_RECORDS_LIST);
+ return;
+ }
BE_STREAM_TO_UINT16 (max_replies, p_req);
if (max_replies > SDP_MAX_RECORDS)
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;
- }
/* Get a list of handles that match the UUIDs given to us */
/* Check if this is a continuation request */
if (*p_req)
{
- if (*p_req++ != SDP_CONTINUATION_LEN || (p_req >= p_req_end))
- {
+ if (*p_req++ != SDP_CONTINUATION_LEN ||
+ (p_req + sizeof(cont_offset) > p_req_end)) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_CONT_STATE,
SDP_TEXT_BAD_CONT_LEN);
return;
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)
- {
- sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_SERV_REC_HDL, SDP_TEXT_BAD_HANDLE);
+ if (p_req + sizeof(rec_handle) + sizeof(max_list_len) > p_req_end) {
+ android_errorWriteLog(0x534e4554, "69384124");
+ 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);
p_req = sdpu_extract_attr_seq (p_req, param_len, &attr_seq);
- if ((!p_req) || (!attr_seq.num_attr) || (p_req > p_req_end))
- {
+ if ((!p_req) || (!attr_seq.num_attr) ||
+ (p_req + sizeof(uint8_t) > p_req_end)) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_ATTR_LIST);
return;
}
/* Check if this is a continuation request */
if (*p_req) {
- if (*p_req++ != SDP_CONTINUATION_LEN) {
+ if (*p_req++ != SDP_CONTINUATION_LEN ||
+ (p_req + sizeof(cont_offset) > p_req_end)) {
sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_CONT_STATE,
SDP_TEXT_BAD_CONT_LEN);
return;
/* Extract the UUID sequence to search for */
p_req = sdpu_extract_uid_seq (p_req, param_len, &uid_seq);
- if ((!p_req) || (!uid_seq.num_uids))
- {
+ if ((!p_req) || (!uid_seq.num_uids) ||
+ (p_req + sizeof(uint16_t) > p_req_end)) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_UUID_LIST);
return;
}
p_req = sdpu_extract_attr_seq (p_req, param_len, &attr_seq);
- if ((!p_req) || (!attr_seq.num_attr))
- {
+ if ((!p_req) || (!attr_seq.num_attr) ||
+ (p_req + sizeof(uint8_t) > p_req_end)) {
sdpu_build_n_send_error (p_ccb, trans_num, SDP_INVALID_REQ_SYNTAX, SDP_TEXT_BAD_ATTR_LIST);
return;
}
/* Check if this is a continuation request */
if (*p_req) {
- if (*p_req++ != SDP_CONTINUATION_LEN) {
+ if (*p_req++ != SDP_CONTINUATION_LEN ||
+ (p_req + sizeof(uint16_t) > p_req_end)) {
sdpu_build_n_send_error(p_ccb, trans_num, SDP_INVALID_CONT_STATE,
SDP_TEXT_BAD_CONT_LEN);
return;
/* A UID sequence is composed of a bunch of UIDs. */
+ if (sizeof(descr) > param_len) return (NULL);
+ param_len -= sizeof(descr);
+
BE_STREAM_TO_UINT8 (descr, p);
type = descr >> 3;
size = descr & 7;
seq_len = 16;
break;
case SIZE_IN_NEXT_BYTE:
+ if (sizeof(uint8_t) > param_len) return (NULL);
+ param_len -= sizeof(uint8_t);
BE_STREAM_TO_UINT8 (seq_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (sizeof(uint16_t) > param_len) return (NULL);
+ param_len -= sizeof(uint16_t);
BE_STREAM_TO_UINT16 (seq_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (sizeof(uint32_t) > param_len) return (NULL);
+ param_len -= sizeof(uint32_t);
BE_STREAM_TO_UINT32 (seq_len, p);
break;
default:
return (NULL);
}
- if (seq_len >= param_len)
+ if (seq_len > param_len)
return (NULL);
p_seq_end = p + seq_len;
uuid_len = 16;
break;
case SIZE_IN_NEXT_BYTE:
+ if (p + sizeof(uint8_t) > p_seq_end) return NULL;
BE_STREAM_TO_UINT8 (uuid_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (p + sizeof(uint16_t) > p_seq_end) return NULL;
BE_STREAM_TO_UINT16 (uuid_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (p + sizeof(uint32_t) > p_seq_end) return NULL;
BE_STREAM_TO_UINT32 (uuid_len, p);
break;
default:
}
/* If UUID length is valid, copy it across */
- if ((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16))
- {
+ if (((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16)) &&
+ (p + uuid_len <= p_seq_end)) {
p_seq->uuid_entry[p_seq->num_uids].len = (UINT16) uuid_len;
BE_STREAM_TO_ARRAY (p, p_seq->uuid_entry[p_seq->num_uids].value, (int)uuid_len);
p_seq->num_uids++;
p_seq->num_attr = 0;
/* Get attribute sequence info */
+ if (param_len < sizeof(descr)) return NULL;
+ param_len -= sizeof(descr);
BE_STREAM_TO_UINT8 (descr, p);
type = descr >> 3;
size = descr & 7;
- if (type != DATA_ELE_SEQ_DESC_TYPE)
- return (p);
+ if (type != DATA_ELE_SEQ_DESC_TYPE) return NULL;
switch (size)
{
case SIZE_IN_NEXT_BYTE:
+ if (param_len < sizeof(uint8_t)) return NULL;
+ param_len -= sizeof(uint8_t);
BE_STREAM_TO_UINT8 (list_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (param_len < sizeof(uint16_t)) return NULL;
+ param_len -= sizeof(uint16_t);
BE_STREAM_TO_UINT16 (list_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (param_len < sizeof(uint32_t)) return NULL;
+ param_len -= sizeof(uint32_t);
BE_STREAM_TO_UINT32 (list_len, p);
break;
default:
- return (p);
+ return NULL;
}
- if (list_len > param_len)
- return (p);
+ if (list_len > param_len) return NULL;
p_end_list = p + list_len;
type = descr >> 3;
size = descr & 7;
- if (type != UINT_DESC_TYPE)
- return (p);
+ if (type != UINT_DESC_TYPE) return NULL;
switch (size)
{
attr_len = 4;
break;
case SIZE_IN_NEXT_BYTE:
+ if (p + sizeof(uint8_t) > p_end_list) return NULL;
BE_STREAM_TO_UINT8 (attr_len, p);
break;
case SIZE_IN_NEXT_WORD:
+ if (p + sizeof(uint16_t) > p_end_list) return NULL;
BE_STREAM_TO_UINT16 (attr_len, p);
break;
case SIZE_IN_NEXT_LONG:
+ if (p + sizeof(uint32_t) > p_end_list) return NULL;
BE_STREAM_TO_UINT32 (attr_len, p);
break;
default:
- return (NULL);
+ return NULL;
break;
}
/* Attribute length must be 2-bytes or 4-bytes for a paired entry. */
+ if (p + attr_len > p_end_list) return NULL;
if (attr_len == 2)
{
BE_STREAM_TO_UINT16 (p_seq->attr_entry[p_seq->num_attr].start, p);