Sophie

Sophie

distrib > Mandriva > 2008.0 > x86_64 > by-pkgid > 117387598c0afa99b8e390cef525a920 > files > 2

bluez-3.15-1.1mdv2008.0.src.rpm

--- bluez-libs-3.28/src/sdp.c.cve-2008-2374	2008-03-05 15:15:11.000000000 -0500
+++ bluez-libs-3.28/src/sdp.c	2008-07-14 15:51:24.000000000 -0400
@@ -904,15 +904,76 @@ void sdp_data_free(sdp_data_t *d)
 	free(d);
 }
 
-static sdp_data_t *extract_int(const void *p, int *len)
+int sdp_uuid_extract_safe(const uint8_t *p, int bufsize, uuid_t *uuid, int *scanned)
 {
-	sdp_data_t *d = malloc(sizeof(sdp_data_t));
+	uint8_t type;
+
+	if (bufsize < sizeof(uint8_t)) {
+		SDPERR("Unexpected end of packet");
+		return -1;
+	}
+
+	type = *(const uint8_t *) p;
+
+	if (!SDP_IS_UUID(type)) {
+		SDPERR("Unknown data type : %d expecting a svc UUID\n", type);
+		return -1;
+	}
+	p += sizeof(uint8_t);
+	*scanned += sizeof(uint8_t);
+	bufsize -= sizeof(uint8_t);
+	if (type == SDP_UUID16) {
+		if (bufsize < sizeof(uint16_t)) {
+			SDPERR("Not enough room for 16-bit UUID");
+			return -1;
+		}
+		sdp_uuid16_create(uuid, ntohs(bt_get_unaligned((uint16_t *) p)));
+		*scanned += sizeof(uint16_t);
+		p += sizeof(uint16_t);
+	} else if (type == SDP_UUID32) {
+		if (bufsize < sizeof(uint32_t)) {
+			SDPERR("Not enough room for 32-bit UUID");
+			return -1;
+		}
+		sdp_uuid32_create(uuid, ntohl(bt_get_unaligned((uint32_t *) p)));
+		*scanned += sizeof(uint32_t);
+		p += sizeof(uint32_t);
+	} else {
+		if (bufsize < sizeof(uint128_t)) {
+			SDPERR("Not enough room for 128-bit UUID");
+			return -1;
+		}
+		sdp_uuid128_create(uuid, p);
+		*scanned += sizeof(uint128_t);
+		p += sizeof(uint128_t);
+	}
+	return 0;
+}
+
+int sdp_uuid_extract(const uint8_t *p, uuid_t *uuid, int *scanned)
+{
+	/* Assume p points to a buffer of size at least SDP_MAX_ATTR_LEN,
+	   because we don't have any better information */
+	return sdp_uuid_extract_safe(p, SDP_MAX_ATTR_LEN, uuid, scanned);
+}
+
+static sdp_data_t *extract_int(const void *p, int bufsize, int *len)
+{
+	sdp_data_t *d;
+
+	if (bufsize < sizeof(uint8_t)) {
+		SDPERR("Unexpected end of packet");
+		return NULL;
+	}
+
+	d = malloc(sizeof(sdp_data_t));
 
 	SDPDBG("Extracting integer\n");
 	memset(d, 0, sizeof(sdp_data_t));
 	d->dtd = *(uint8_t *) p;
 	p += sizeof(uint8_t);
 	*len += sizeof(uint8_t);
+	bufsize -= sizeof(uint8_t);
 
 	switch (d->dtd) {
 	case SDP_DATA_NIL:
@@ -920,26 +981,51 @@ static sdp_data_t *extract_int(const voi
 	case SDP_BOOL:
 	case SDP_INT8:
 	case SDP_UINT8:
+		if (bufsize < sizeof(uint8_t)) {
+			SDPERR("Unexpected end of packet");
+			free(d);
+			return NULL;
+		}
 		*len += sizeof(uint8_t);
 		d->val.uint8 = *(uint8_t *) p;
 		break;
 	case SDP_INT16:
 	case SDP_UINT16:
+		if (bufsize < sizeof(uint16_t)) {
+			SDPERR("Unexpected end of packet");
+			free(d);
+			return NULL;
+		}
 		*len += sizeof(uint16_t);
 		d->val.uint16 = ntohs(bt_get_unaligned((uint16_t *) p));
 		break;
 	case SDP_INT32:
 	case SDP_UINT32:
+		if (bufsize < sizeof(uint32_t)) {
+			SDPERR("Unexpected end of packet");
+			free(d);
+			return NULL;
+		}
 		*len += sizeof(uint32_t);
 		d->val.uint32 = ntohl(bt_get_unaligned((uint32_t *) p));
 		break;
 	case SDP_INT64:
 	case SDP_UINT64:
+		if (bufsize < sizeof(uint64_t)) {
+			SDPERR("Unexpected end of packet");
+			free(d);
+			return NULL;
+		}
 		*len += sizeof(uint64_t);
 		d->val.uint64 = ntoh64(bt_get_unaligned((uint64_t *) p));
 		break;
 	case SDP_INT128:
 	case SDP_UINT128:
+		if (bufsize < sizeof(uint128_t)) {
+			SDPERR("Unexpected end of packet");
+			free(d);
+			return NULL;
+		}
 		*len += sizeof(uint128_t);
 		ntoh128((uint128_t *) p, &d->val.uint128);
 		break;
@@ -950,13 +1036,13 @@ static sdp_data_t *extract_int(const voi
 	return d;
 }
 
-static sdp_data_t *extract_uuid(const uint8_t *p, int *len, sdp_record_t *rec)
+static sdp_data_t *extract_uuid(const uint8_t *p, int bufsize, int *len, sdp_record_t *rec)
 {
 	sdp_data_t *d = malloc(sizeof(sdp_data_t));
 
 	SDPDBG("Extracting UUID");
 	memset(d, 0, sizeof(sdp_data_t));
-	if (sdp_uuid_extract(p, &d->val.uuid, len) < 0) {
+	if (sdp_uuid_extract_safe(p, bufsize, &d->val.uuid, len) < 0) {
 		free(d);
 		return NULL;
 	}
@@ -969,29 +1055,49 @@ static sdp_data_t *extract_uuid(const ui
 /*
  * Extract strings from the PDU (could be service description and similar info) 
  */
-static sdp_data_t *extract_str(const void *p, int *len)
+static sdp_data_t *extract_str(const void *p, int bufsize, int *len)
 {
 	char *s;
 	int n;
-	sdp_data_t *d = malloc(sizeof(sdp_data_t));
+	sdp_data_t *d;
+
+	if (bufsize < sizeof(uint8_t)) {
+		SDPERR("Unexpected end of packet");
+		return NULL;
+	}
+
+	d = malloc(sizeof(sdp_data_t));
 
 	memset(d, 0, sizeof(sdp_data_t));
 	d->dtd = *(uint8_t *) p;
 	p += sizeof(uint8_t);
 	*len += sizeof(uint8_t);
+	bufsize -= sizeof(uint8_t);
 
 	switch (d->dtd) {
 	case SDP_TEXT_STR8:
 	case SDP_URL_STR8:
+		if (bufsize < sizeof(uint8_t)) {
+			SDPERR("Unexpected end of packet");
+			free(d);
+			return NULL;
+		}
 		n = *(uint8_t *) p;
 		p += sizeof(uint8_t);
-		*len += sizeof(uint8_t) + n;
+		*len += sizeof(uint8_t);
+		bufsize -= sizeof(uint8_t);
 		break;
 	case SDP_TEXT_STR16:
 	case SDP_URL_STR16:
+		if (bufsize < sizeof(uint16_t)) {
+			SDPERR("Unexpected end of packet");
+			free(d);
+			return NULL;
+		}
 		n = ntohs(bt_get_unaligned((uint16_t *) p));
 		p += sizeof(uint16_t);
 		*len += sizeof(uint16_t) + n;
+		bufsize -= sizeof(uint16_t);
 		break;
 	default:
 		SDPERR("Sizeof text string > UINT16_MAX\n");
@@ -999,10 +1105,23 @@ static sdp_data_t *extract_str(const voi
 		return 0;
 	}
 
+	if (bufsize < n) {
+		SDPERR("String too long to fit in packet");
+		free(d);
+		return NULL;
+	}
+
 	s = malloc(n + 1);
+	if (!s) {
+		SDPERR("Not enough memory for incoming string");
+		free(d);
+		return NULL;
+	}
 	memset(s, 0, n + 1);
 	memcpy(s, p, n);
 
+	*len += n;
+
 	SDPDBG("Len : %d\n", n);
 	SDPDBG("Str : %s\n", s);
 
@@ -1011,7 +1130,67 @@ static sdp_data_t *extract_str(const voi
 	return d;
 }
 
-static sdp_data_t *extract_seq(const void *p, int *len, sdp_record_t *rec)
+/*
+ * Extract the sequence type and its length, and return offset into buf
+ * or 0 on failure.
+ */
+int sdp_extract_seqtype_safe(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size)
+{
+	uint8_t dtd;
+	int scanned = sizeof(uint8_t);
+
+	if (bufsize < sizeof(uint8_t)) {
+		SDPERR("Unexpected end of packet");
+		return 0;
+	}
+
+	dtd = *(uint8_t *) buf;
+	buf += sizeof(uint8_t);
+	bufsize -= sizeof(uint8_t);
+	*dtdp = dtd;
+	switch (dtd) {
+	case SDP_SEQ8:
+	case SDP_ALT8:
+		if (bufsize < sizeof(uint8_t)) {
+			SDPERR("Unexpected end of packet");
+			return 0;
+		}
+		*size = *(uint8_t *) buf;
+		scanned += sizeof(uint8_t);
+		break;
+	case SDP_SEQ16:
+	case SDP_ALT16:
+		if (bufsize < sizeof(uint16_t)) {
+			SDPERR("Unexpected end of packet");
+			return 0;
+		}
+		*size = ntohs(bt_get_unaligned((uint16_t *) buf));
+		scanned += sizeof(uint16_t);
+		break;
+	case SDP_SEQ32:
+	case SDP_ALT32:
+		if (bufsize < sizeof(uint32_t)) {
+			SDPERR("Unexpected end of packet");
+			return 0;
+		}
+		*size = ntohl(bt_get_unaligned((uint32_t *) buf));
+		scanned += sizeof(uint32_t);
+		break;
+	default:
+		SDPERR("Unknown sequence type, aborting\n");
+		return 0;
+	}
+	return scanned;
+}
+
+int sdp_extract_seqtype(const uint8_t *buf, uint8_t *dtdp, int *size)
+{
+	/* Assume buf points to a buffer of size at least SDP_MAX_ATTR_LEN,
+	   because we don't have any better information */
+	return sdp_extract_seqtype_safe(buf, SDP_MAX_ATTR_LEN, dtdp, size);
+}
+
+static sdp_data_t *extract_seq(const void *p, int bufsize, int *len, sdp_record_t *rec)
 {
 	int seqlen, n = 0;
 	sdp_data_t *curr, *prev;
@@ -1019,17 +1198,24 @@ static sdp_data_t *extract_seq(const voi
 
 	SDPDBG("Extracting SEQ");
 	memset(d, 0, sizeof(sdp_data_t));
-	*len = sdp_extract_seqtype(p, &d->dtd, &seqlen);
+	*len = sdp_extract_seqtype_safe(p, bufsize, &d->dtd, &seqlen);
 	SDPDBG("Sequence Type : 0x%x length : 0x%x\n", d->dtd, seqlen);
 
 	if (*len == 0)
 		return d;
 
+	if (*len > bufsize) {
+		SDPERR("Packet not big enough to hold sequence.");
+		free(d);
+		return NULL;
+	}
+
 	p += *len;
+	bufsize -= *len;
 	curr = prev = NULL;
 	while (n < seqlen) {
 		int attrlen = 0;
-		curr = sdp_extract_attr(p, &attrlen, rec);
+		curr = sdp_extract_attr_safe(p, bufsize, &attrlen, rec);
 		if (curr == NULL)
 			break;
 
@@ -1040,6 +1226,7 @@ static sdp_data_t *extract_seq(const voi
 		prev = curr;
 		p += attrlen;
 		n += attrlen;
+		bufsize -= attrlen;
 
 		SDPDBG("Extracted: %d SequenceLength: %d", n, seqlen);
 	}
@@ -1048,11 +1235,18 @@ static sdp_data_t *extract_seq(const voi
 	return d;
 }
 
-sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec)
+sdp_data_t *sdp_extract_attr_safe(const uint8_t *p, int bufsize, int *size, sdp_record_t *rec)
 {
 	sdp_data_t *elem;
 	int n = 0;
-	uint8_t dtd = *(const uint8_t *)p;
+	uint8_t dtd;
+
+	if (bufsize < sizeof(uint8_t)) {
+		SDPERR("Unexpected end of packet");
+		return NULL;
+	}
+
+	dtd = *(const uint8_t *)p;
 
 	SDPDBG("extract_attr: dtd=0x%x", dtd);
 	switch (dtd) {
@@ -1068,12 +1262,12 @@ sdp_data_t *sdp_extract_attr(const uint8
 	case SDP_INT32:
 	case SDP_INT64:
 	case SDP_INT128:
-		elem = extract_int(p, &n);
+		elem = extract_int(p, bufsize, &n);
 		break;
 	case SDP_UUID16:
 	case SDP_UUID32:
 	case SDP_UUID128:
-		elem = extract_uuid(p, &n, rec);
+		elem = extract_uuid(p, bufsize, &n, rec);
 		break;
 	case SDP_TEXT_STR8:
 	case SDP_TEXT_STR16:
@@ -1081,7 +1275,7 @@ sdp_data_t *sdp_extract_attr(const uint8
 	case SDP_URL_STR8:
 	case SDP_URL_STR16:
 	case SDP_URL_STR32:
-		elem = extract_str(p, &n);
+		elem = extract_str(p, bufsize, &n);
 		break;
 	case SDP_SEQ8:
 	case SDP_SEQ16:
@@ -1089,7 +1283,7 @@ sdp_data_t *sdp_extract_attr(const uint8
 	case SDP_ALT8:
 	case SDP_ALT16:
 	case SDP_ALT32:
-		elem = extract_seq(p, &n, rec);
+		elem = extract_seq(p, bufsize, &n, rec);
 		break;
 	default:
 		SDPERR("Unknown data descriptor : 0x%x terminating\n", dtd);
@@ -1099,6 +1293,13 @@ sdp_data_t *sdp_extract_attr(const uint8
 	return elem;
 }
 
+sdp_data_t *sdp_extract_attr(const uint8_t *p, int *size, sdp_record_t *rec)
+{
+	/* Assume p points to a buffer of size at least SDP_MAX_ATTR_LEN,
+	   because we don't have any better information */
+	return sdp_extract_attr_safe(p, SDP_MAX_ATTR_LEN, size, rec);
+}
+
 #ifdef SDP_DEBUG
 static void attr_print_func(void *value, void *userData)
 {
@@ -1122,7 +1323,7 @@ void sdp_print_service_attr(sdp_list_t *
 }
 #endif
 
-sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned)
+sdp_record_t *sdp_extract_pdu_safe(const uint8_t *buf, int bufsize, int *scanned)
 {
 	int extracted = 0, seqlen = 0;
 	uint8_t dtd;
@@ -1130,21 +1331,30 @@ sdp_record_t *sdp_extract_pdu(const uint
 	sdp_record_t *rec = sdp_record_alloc();
 	const uint8_t *p = buf;
 
-	*scanned = sdp_extract_seqtype(buf, &dtd, &seqlen);
+	*scanned = sdp_extract_seqtype_safe(buf, bufsize, &dtd, &seqlen);
 	p += *scanned;
+	bufsize -= *scanned;
 	rec->attrlist = NULL;
-	while (extracted < seqlen) {
+
+	while (extracted < seqlen && bufsize > 0) {
 		int n = sizeof(uint8_t), attrlen = 0;
 		sdp_data_t *data = NULL;
 
-		SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d", seqlen, extracted);
+		SDPDBG("Extract PDU, sequenceLength: %d localExtractedLength: %d",
+							seqlen, extracted);
+
+		if (bufsize < n + sizeof(uint16_t)) {
+			SDPERR("Unexpected end of packet");
+			break;
+		}
+
 		dtd = *(uint8_t *) p;
 		attr = ntohs(bt_get_unaligned((uint16_t *) (p + n)));
 		n += sizeof(uint16_t);
 
 		SDPDBG("DTD of attrId : %d Attr id : 0x%x \n", dtd, attr);
 
-		data = sdp_extract_attr(p + n, &attrlen, rec);
+		data = sdp_extract_attr_safe(p + n, bufsize - n, &attrlen, rec);
 
 		SDPDBG("Attr id : 0x%x attrValueLength : %d\n", attr, attrlen);
 
@@ -1162,9 +1372,11 @@ sdp_record_t *sdp_extract_pdu(const uint
 
 		extracted += n;
 		p += n;
+		bufsize -= n;
 		sdp_attr_replace(rec, attr, data);
+
 		SDPDBG("Extract PDU, seqLength: %d localExtractedLength: %d",
-					seqlen, extracted);
+							seqlen, extracted);
 	}
 #ifdef SDP_DEBUG
 	SDPDBG("Successful extracting of Svc Rec attributes\n");
@@ -1174,6 +1386,13 @@ sdp_record_t *sdp_extract_pdu(const uint
 	return rec;
 }
 
+sdp_record_t *sdp_extract_pdu(const uint8_t *buf, int *scanned)
+{
+	/* Assume buf points to a buffer of size at least SDP_MAX_ATTR_LEN,
+	   because we don't have any better information */
+	return sdp_extract_pdu_safe(buf, SDP_MAX_ATTR_LEN, scanned);
+}
+
 #ifdef SDP_DEBUG
 static void print_dataseq(sdp_data_t *p)
 {
@@ -1262,40 +1481,6 @@ sdp_data_t *sdp_data_get(const sdp_recor
 	return NULL;
 }
 
-/*
- * Extract the sequence type and its length, and return offset into buf
- * or 0 on failure.
- */
-int sdp_extract_seqtype(const uint8_t *buf, uint8_t *dtdp, int *size)
-{
-	uint8_t dtd = *(uint8_t *) buf;
-	int scanned = sizeof(uint8_t);
-
-	buf += sizeof(uint8_t);
-	*dtdp = dtd;
-	switch (dtd) {
-	case SDP_SEQ8:
-	case SDP_ALT8:
-		*size = *(uint8_t *) buf;
-		scanned += sizeof(uint8_t);
-		break;
-	case SDP_SEQ16:
-	case SDP_ALT16:
-		*size = ntohs(bt_get_unaligned((uint16_t *) buf));
-		scanned += sizeof(uint16_t);
-		break;
-	case SDP_SEQ32:
-	case SDP_ALT32:
-		*size = ntohl(bt_get_unaligned((uint32_t *) buf));
-		scanned += sizeof(uint32_t);
-		break;
-	default:
-		SDPERR("Unknown sequence type, aborting\n");
-		return 0;
-	}
-	return scanned;
-}
-
 int sdp_send_req(sdp_session_t *session, uint8_t *buf, uint32_t size)
 {
 	uint32_t sent = 0;
@@ -2328,32 +2513,6 @@ int sdp_uuid_to_proto(uuid_t *uuid)
 	return 0;
 }
 
-int sdp_uuid_extract(const uint8_t *p, uuid_t *uuid, int *scanned)
-{
-	uint8_t type = *(const uint8_t *) p;
-
-	if (!SDP_IS_UUID(type)) {
-		SDPERR("Unknown data type : %d expecting a svc UUID\n", type);
-		return -1;
-	}
-	p += sizeof(uint8_t);
-	*scanned += sizeof(uint8_t);
-	if (type == SDP_UUID16) {
-		sdp_uuid16_create(uuid, ntohs(bt_get_unaligned((uint16_t *) p)));
-		*scanned += sizeof(uint16_t);
-		p += sizeof(uint16_t);
-	} else if (type == SDP_UUID32) {
-		sdp_uuid32_create(uuid, ntohl(bt_get_unaligned((uint32_t *) p)));
-		*scanned += sizeof(uint32_t);
-		p += sizeof(uint32_t);
-	} else {
-		sdp_uuid128_create(uuid, p);
-		*scanned += sizeof(uint128_t);
-		p += sizeof(uint128_t);
-	}
-	return 0;
-}
-
 /*
  * This function appends data to the PDU buffer "dst" from source "src". 
  * The data length is also computed and set.
@@ -2483,6 +2642,13 @@ int sdp_device_record_register_binary(sd
 	if (status < 0)
 		goto end;
 
+	if (rspsize < sizeof(sdp_pdu_hdr_t)) {
+		SDPERR("Unexpected end of packet");
+		errno = EPROTO;
+		status = -1;
+		goto end;
+	}
+
 	rsphdr = (sdp_pdu_hdr_t *) rsp;
 	p = rsp + sizeof(sdp_pdu_hdr_t);
 
@@ -2589,6 +2755,13 @@ int sdp_device_record_unregister_binary(
 	if (status < 0)
 		goto end;
 
+	if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) {
+		SDPERR("Unexpected end of packet");
+		errno = EPROTO;
+		status = -1;
+		goto end;
+	}
+
 	rsphdr = (sdp_pdu_hdr_t *) rspbuf;
 	p = rspbuf + sizeof(sdp_pdu_hdr_t);
 	status = bt_get_unaligned((uint16_t *) p);
@@ -2688,6 +2861,13 @@ int sdp_device_record_update(sdp_session
 	if (status < 0)
 		goto end;
 
+	if (rspsize < sizeof(sdp_pdu_hdr_t) + sizeof(uint16_t)) {
+		SDPERR("Unexpected end of packet");
+		errno = EPROTO;
+		status = -1;
+		goto end;
+	}
+
 	SDPDBG("Send req status : %d\n", status);
 
 	rsphdr = (sdp_pdu_hdr_t *) rspbuf;
@@ -2763,18 +2943,23 @@ void sdp_pattern_add_uuidseq(sdp_record_
  * 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;
 }
@@ -2791,7 +2976,7 @@ static int gen_dataseq_pdu(uint8_t *dst,
 
 	// Fill up the value and the dtd arrays
 	SDPDBG("");
-	
+
 	memset(&buf, 0, sizeof(sdp_buf_t));
 	buf.data = malloc(256);
 	buf.buf_size = 256;
@@ -2842,12 +3027,17 @@ typedef struct {
 	unsigned char data[16];
 } __attribute__ ((packed)) sdp_cstate_t;
 
-static int copy_cstate(uint8_t *pdata, const sdp_cstate_t *cstate)
+static int copy_cstate(uint8_t *pdata, int pdata_len, const sdp_cstate_t *cstate)
 {
 	if (cstate) {
-		*pdata++ = cstate->length;
-		memcpy(pdata, cstate->data, cstate->length);
-		return cstate->length + 1;
+		uint8_t len = cstate->length;
+		if (len >= pdata_len) {
+			SDPERR("Continuation state size exceeds internal buffer");
+			len = pdata_len - 1;
+		}
+		*pdata++ = len;
+		memcpy(pdata, cstate->data, len);
+		return len + 1;
 	}
 	*pdata = 0;
 	return 1;
@@ -2889,7 +3079,7 @@ int sdp_service_search_req(sdp_session_t
 	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;
@@ -2927,7 +3117,8 @@ int sdp_service_search_req(sdp_session_t
 
 	do {
 		// Add continuation state or NULL (first time)
-		reqsize = _reqsize + copy_cstate(_pdata, cstate);
+		reqsize = _reqsize + copy_cstate(_pdata,
+					SDP_REQ_BUFFER_SIZE - _reqsize, cstate);
 
 		// Set the request header's param length
 		reqhdr->plen = htons(reqsize - sizeof(sdp_pdu_hdr_t));
@@ -2941,7 +3132,12 @@ int sdp_service_search_req(sdp_session_t
 		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);
 
@@ -2952,14 +3148,23 @@ int sdp_service_search_req(sdp_session_t
 		}
 		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);
@@ -2969,12 +3174,18 @@ int sdp_service_search_req(sdp_session_t
 			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) {
@@ -2985,7 +3196,7 @@ int sdp_service_search_req(sdp_session_t
 		}
 	} while (cstate);
 
-  end:
+end:
 	if (reqbuf)
 		free(reqbuf);
 	if (rspbuf)
@@ -3033,7 +3244,7 @@ sdp_record_t *sdp_service_attr_req(sdp_s
 	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;
@@ -3089,7 +3300,8 @@ sdp_record_t *sdp_service_attr_req(sdp_s
 
 	do {
 		// add NULL continuation state
-		reqsize = _reqsize + copy_cstate(_pdata, cstate);
+		reqsize = _reqsize + copy_cstate(_pdata,
+					SDP_REQ_BUFFER_SIZE - _reqsize, cstate);
 
 		// set the request header's param length
 		reqhdr->tid  = htons(sdp_gen_tid(session));
@@ -3098,6 +3310,13 @@ sdp_record_t *sdp_service_attr_req(sdp_s
 		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) {
@@ -3106,11 +3325,25 @@ sdp_record_t *sdp_service_attr_req(sdp_s
 			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);
@@ -3137,15 +3370,17 @@ sdp_record_t *sdp_service_attr_req(sdp_s
 
 	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;
 	}
 	
-  end:
+end:
 	if (reqbuf)
 		free(reqbuf);
 	if (rsp_concat_buf.data)
@@ -3310,7 +3545,7 @@ int sdp_service_search_async(sdp_session
 	pdata += sizeof(uint16_t);
 
 	// set the request header's param length
-	cstate_len = copy_cstate(pdata, NULL);
+	cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL);
 	reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t));
 
 	if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) {
@@ -3424,7 +3659,7 @@ int sdp_service_attr_async(sdp_session_t
 	SDPDBG("Attr list length : %d\n", seqlen);
 
 	// set the request header's param length
-	cstate_len = copy_cstate(pdata, NULL);
+	cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL);
 	reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t));
 
 	if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) {
@@ -3543,7 +3778,7 @@ int sdp_service_search_attr_async(sdp_se
 	t->reqsize += seqlen;
 
 	// set the request header's param length
-	cstate_len = copy_cstate(pdata, NULL);
+	cstate_len = copy_cstate(pdata, SDP_REQ_BUFFER_SIZE - t->reqsize, NULL);
 	reqhdr->plen = htons((t->reqsize + cstate_len) - sizeof(sdp_pdu_hdr_t));
 
 	if (sdp_send_req(session, t->reqbuf, t->reqsize + cstate_len) < 0) {
@@ -3756,7 +3991,8 @@ int sdp_process(sdp_session_t *session)
 		reqhdr->tid = htons(sdp_gen_tid(session));
 
 		// add continuation state
-		cstate_len = copy_cstate(t->reqbuf + t->reqsize, pcstate);
+		cstate_len = copy_cstate(t->reqbuf + t->reqsize,
+				SDP_REQ_BUFFER_SIZE - t->reqsize, pcstate);
 
 		reqsize = t->reqsize + cstate_len;
 
@@ -3835,7 +4071,7 @@ int sdp_service_search_attr_req(sdp_sess
 	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;
@@ -3899,12 +4135,19 @@ int sdp_service_search_attr_req(sdp_sess
 		reqhdr->tid = htons(sdp_gen_tid(session));
 
 		// add continuation state (can be null)
-		reqsize = _reqsize + copy_cstate(_pdata, cstate);
+		reqsize = _reqsize + copy_cstate(_pdata,
+					SDP_REQ_BUFFER_SIZE - _reqsize, cstate);
 
 		// set the request header's param length
 		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;
@@ -3916,9 +4159,25 @@ int sdp_service_search_attr_req(sdp_sess
 		}
 	  
 		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);
@@ -3945,24 +4204,27 @@ int sdp_service_search_attr_req(sdp_sess
 	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;
@@ -3974,13 +4236,14 @@ int sdp_service_search_attr_req(sdp_sess
 				}
 				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;
--- bluez-libs-3.28/include/sdp_lib.h.cve-2008-2374	2008-02-01 18:14:55.000000000 -0500
+++ bluez-libs-3.28/include/sdp_lib.h	2008-07-14 15:35:49.000000000 -0400
@@ -479,6 +479,7 @@ void sdp_uuid32_to_uuid128(uuid_t *uuid1
 int sdp_uuid128_to_uuid(uuid_t *uuid);
 int sdp_uuid_to_proto(uuid_t *uuid);
 int sdp_uuid_extract(const uint8_t *buffer, uuid_t *uuid, int *scanned);
+int sdp_uuid_extract_safe(const uint8_t *buffer, int bufsize, uuid_t *uuid, int *scanned);
 void sdp_uuid_print(const uuid_t *uuid);
 
 #define MAX_LEN_UUID_STR 37
@@ -585,7 +586,7 @@ static inline int sdp_get_icon_url(const
 }
 
 sdp_record_t *sdp_extract_pdu(const uint8_t *pdata, int *scanned);
-sdp_data_t *sdp_extract_string(uint8_t *, int *);
+sdp_record_t *sdp_extract_pdu_safe(const uint8_t *pdata, int bufsize, int *scanned);
 
 void sdp_data_print(sdp_data_t *data);
 void sdp_print_service_attr(sdp_list_t *alist);
@@ -601,8 +602,10 @@ int sdp_gen_pdu(sdp_buf_t *pdu, sdp_data
 int sdp_gen_record_pdu(const sdp_record_t *rec, sdp_buf_t *pdu);
 
 int sdp_extract_seqtype(const uint8_t *buf, uint8_t *dtdp, int *seqlen);
+int sdp_extract_seqtype_safe(const uint8_t *buf, int bufsize, uint8_t *dtdp, int *size);
 
 sdp_data_t *sdp_extract_attr(const uint8_t *pdata, int *extractedLength, sdp_record_t *rec);
+sdp_data_t *sdp_extract_attr_safe(const uint8_t *pdata, int bufsize, int *extractedLength, sdp_record_t *rec);
 
 void sdp_pattern_add_uuid(sdp_record_t *rec, uuid_t *uuid);
 void sdp_pattern_add_uuidseq(sdp_record_t *rec, sdp_list_t *seq);