summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2008-06-23 06:18:33 +0000
committerMarcel Holtmann <marcel@holtmann.org>2008-06-23 06:18:33 +0000
commit121c632f01e3f49a69a9d637e0da4d25c2ee090d (patch)
tree85f28759e97c03de291b52dc65a7f42f9829cb9d
parent0a8f7c9206e17ab118966bf7da8a053ef34dce84 (diff)
Have the service routines use the new safe functions
-rw-r--r--src/sdp.c98
1 files changed, 86 insertions, 12 deletions
diff --git a/src/sdp.c b/src/sdp.c
index 59686388..4217aedd 100644
--- a/src/sdp.c
+++ b/src/sdp.c
@@ -2923,18 +2923,23 @@ void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq)
* handles are not in "data element sequence" form, but just like
* an array of service handles
*/
-static void extract_record_handle_seq(uint8_t *pdu, sdp_list_t **seq, int count, int *scanned)
+static void extract_record_handle_seq(uint8_t *pdu, int bufsize, sdp_list_t **seq, int count, int *scanned)
{
sdp_list_t *pSeq = *seq;
uint8_t *pdata = pdu;
int n;
for (n = 0; n < count; n++) {
+ if (bufsize < sizeof(uint32_t)) {
+ SDPERR("Unexpected end of packet");
+ break;
+ }
uint32_t *pSvcRec = malloc(sizeof(uint32_t));
*pSvcRec = ntohl(bt_get_unaligned((uint32_t *) pdata));
pSeq = sdp_list_append(pSeq, pSvcRec);
pdata += sizeof(uint32_t);
*scanned += sizeof(uint32_t);
+ bufsize -= sizeof(uint32_t);
}
*seq = pSeq;
}
@@ -3054,7 +3059,7 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search,
uint32_t reqsize = 0, _reqsize;
uint32_t rspsize = 0, rsplen;
int seqlen = 0;
- int scanned, total_rec_count, rec_count;
+ int scanned, total_rec_count, rec_count, pdata_len;
uint8_t *pdata, *_pdata;
uint8_t *reqbuf, *rspbuf;
sdp_pdu_hdr_t *reqhdr, *rsphdr;
@@ -3107,7 +3112,12 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search,
if (status < 0)
goto end;
- rsplen = 0;
+ if (rspsize < sizeof(sdp_pdu_hdr_t)) {
+ SDPERR("Unexpected end of packet");
+ status = -1;
+ goto end;
+ }
+
rsphdr = (sdp_pdu_hdr_t *) rspbuf;
rsplen = ntohs(rsphdr->plen);
@@ -3118,14 +3128,23 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search,
}
scanned = 0;
pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
+ pdata_len = rspsize - sizeof(sdp_pdu_hdr_t);
+
+ if (pdata_len < sizeof(uint16_t) + sizeof(uint16_t)) {
+ SDPERR("Unexpected end of packet");
+ status = -1;
+ goto end;
+ }
// net service record match count
total_rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
pdata += sizeof(uint16_t);
scanned += sizeof(uint16_t);
+ pdata_len -= sizeof(uint16_t);
rec_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
pdata += sizeof(uint16_t);
scanned += sizeof(uint16_t);
+ pdata_len -= sizeof(uint16_t);
SDPDBG("Total svc count: %d\n", total_rec_count);
SDPDBG("Current svc count: %d\n", rec_count);
@@ -3135,12 +3154,18 @@ int sdp_service_search_req(sdp_session_t *session, const sdp_list_t *search,
status = -1;
goto end;
}
- extract_record_handle_seq(pdata, rsp, rec_count, &scanned);
+ extract_record_handle_seq(pdata, pdata_len, rsp, rec_count, &scanned);
SDPDBG("BytesScanned : %d\n", scanned);
if (rsplen > scanned) {
uint8_t cstate_len;
+ if (rspsize < sizeof(sdp_pdu_hdr_t) + scanned + sizeof(uint8_t)) {
+ SDPERR("Unexpected end of packet: continuation state data missing");
+ status = -1;
+ goto end;
+ }
+
pdata = rspbuf + sizeof(sdp_pdu_hdr_t) + scanned;
cstate_len = *(uint8_t *) pdata;
if (cstate_len > 0) {
@@ -3199,7 +3224,7 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle,
uint32_t reqsize = 0, _reqsize;
uint32_t rspsize = 0, rsp_count;
int attr_list_len = 0;
- int seqlen = 0;
+ int seqlen = 0, pdata_len;
uint8_t *pdata, *_pdata;
uint8_t *reqbuf, *rspbuf;
sdp_pdu_hdr_t *reqhdr, *rsphdr;
@@ -3265,6 +3290,13 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle,
status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
if (status < 0)
goto end;
+
+ if (rspsize < sizeof(sdp_pdu_hdr_t)) {
+ SDPERR("Unexpected end of packet");
+ status = -1;
+ goto end;
+ }
+
rsp_count = 0;
rsphdr = (sdp_pdu_hdr_t *) rspbuf;
if (rsphdr->pdu_id == SDP_ERROR_RSP) {
@@ -3273,11 +3305,25 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle,
goto end;
}
pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
+ pdata_len = rspsize - sizeof(sdp_pdu_hdr_t);
+
+ if (pdata_len < sizeof(uint16_t)) {
+ SDPERR("Unexpected end of packet");
+ status = -1;
+ goto end;
+ }
+
rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
attr_list_len += rsp_count;
pdata += sizeof(uint16_t);
+ pdata_len -= sizeof(uint16_t);
// if continuation state set need to re-issue request before parsing
+ if (pdata_len < rsp_count + sizeof(uint8_t)) {
+ SDPERR("Unexpected end of packet: continuation state data missing");
+ status = -1;
+ goto end;
+ }
cstate_len = *(uint8_t *) (pdata + rsp_count);
SDPDBG("Response id : %d\n", rsphdr->pdu_id);
@@ -3304,9 +3350,11 @@ sdp_record_t *sdp_service_attr_req(sdp_session_t *session, uint32_t handle,
if (attr_list_len > 0) {
int scanned = 0;
- if (rsp_concat_buf.data_size != 0)
+ if (rsp_concat_buf.data_size != 0) {
pdata = rsp_concat_buf.data;
- rec = sdp_extract_pdu(pdata, &scanned);
+ pdata_len = rsp_concat_buf.data_size;
+ }
+ rec = sdp_extract_pdu_safe(pdata, pdata_len, &scanned);
if (!rec)
status = -1;
@@ -4003,7 +4051,7 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search
uint32_t reqsize = 0, _reqsize;
uint32_t rspsize = 0;
int seqlen = 0, attr_list_len = 0;
- int rsp_count = 0, cstate_len = 0;
+ int rsp_count = 0, cstate_len = 0, pdata_len;
uint8_t *pdata, *_pdata;
uint8_t *reqbuf, *rspbuf;
sdp_pdu_hdr_t *reqhdr, *rsphdr;
@@ -4074,6 +4122,12 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search
reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
rsphdr = (sdp_pdu_hdr_t *) rspbuf;
status = sdp_send_req_w4_rsp(session, reqbuf, rspbuf, reqsize, &rspsize);
+ if (rspsize < sizeof(sdp_pdu_hdr_t)) {
+ SDPERR("Unexpected end of packet");
+ status = -1;
+ goto end;
+ }
+
if (status < 0) {
SDPDBG("Status : 0x%x\n", rsphdr->pdu_id);
goto end;
@@ -4085,9 +4139,25 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search
}
pdata = rspbuf + sizeof(sdp_pdu_hdr_t);
+ pdata_len = rspsize - sizeof(sdp_pdu_hdr_t);
+
+ if (pdata_len < sizeof(uint16_t)) {
+ SDPERR("Unexpected end of packet");
+ status = -1;
+ goto end;
+ }
+
rsp_count = ntohs(bt_get_unaligned((uint16_t *) pdata));
attr_list_len += rsp_count;
pdata += sizeof(uint16_t); // pdata points to attribute list
+ pdata_len -= sizeof(uint16_t);
+
+ if (pdata_len < rsp_count + sizeof(uint8_t)) {
+ SDPERR("Unexpected end of packet: continuation state data missing");
+ status = -1;
+ goto end;
+ }
+
cstate_len = *(uint8_t *) (pdata + rsp_count);
SDPDBG("Attrlist byte count : %d\n", attr_list_len);
@@ -4114,24 +4184,27 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search
if (attr_list_len > 0) {
int scanned = 0;
- if (rsp_concat_buf.data_size != 0)
+ if (rsp_concat_buf.data_size != 0) {
pdata = rsp_concat_buf.data;
+ pdata_len = rsp_concat_buf.data_size;
+ }
/*
* Response is a sequence of sequence(s) for one or
* more data element sequence(s) representing services
* for which attributes are returned
*/
- scanned = sdp_extract_seqtype(pdata, &dataType, &seqlen);
+ scanned = sdp_extract_seqtype_safe(pdata, pdata_len, &dataType, &seqlen);
SDPDBG("Bytes scanned : %d\n", scanned);
SDPDBG("Seq length : %d\n", seqlen);
if (scanned && seqlen) {
pdata += scanned;
+ pdata_len -= scanned;
do {
int recsize = 0;
- sdp_record_t *rec = sdp_extract_pdu(pdata, &recsize);
+ sdp_record_t *rec = sdp_extract_pdu_safe(pdata, pdata_len, &recsize);
if (rec == NULL) {
SDPERR("SVC REC is null\n");
status = -1;
@@ -4143,13 +4216,14 @@ int sdp_service_search_attr_req(sdp_session_t *session, const sdp_list_t *search
}
scanned += recsize;
pdata += recsize;
+ pdata_len -= recsize;
SDPDBG("Loc seq length : %d\n", recsize);
SDPDBG("Svc Rec Handle : 0x%x\n", rec->handle);
SDPDBG("Bytes scanned : %d\n", scanned);
SDPDBG("Attrlist byte count : %d\n", attr_list_len);
rec_list = sdp_list_append(rec_list, rec);
- } while (scanned < attr_list_len);
+ } while (scanned < attr_list_len && pdata_len > 0);
SDPDBG("Successful scan of service attr lists\n");
*rsp = rec_list;