diff -Nur gaim-0.58~/src/protocols/oscar/aim.h gaim-0.58/src/protocols/oscar/aim.h
--- gaim-0.58~/src/protocols/oscar/aim.h	2002-05-05 20:07:05.000000000 +0100
+++ gaim-0.58/src/protocols/oscar/aim.h	2005-02-20 11:27:37.491526159 +0000
@@ -702,7 +702,7 @@
 } aim_mpmsg_section_t;
 
 typedef struct aim_mpmsg_s {
-	int numparts;
+	unsigned int numparts;
 	aim_mpmsg_section_t *parts;
 } aim_mpmsg_t;
 
@@ -737,8 +737,8 @@
 	fu32_t iconsum;
 
 	/* Only used if AIM_IMFLAGS_CUSTOMFEATURES is set */
+	fu16_t featureslen;
 	fu8_t *features;
-	fu8_t featureslen;
 
 	/* Only used if AIM_IMFLAGS_CUSTOMCHARSET is set and mpmsg not used */
 	fu16_t charset;
diff -Nur gaim-0.58~/src/protocols/oscar/im.c gaim-0.58/src/protocols/oscar/im.c
--- gaim-0.58~/src/protocols/oscar/im.c	2002-05-05 20:02:06.000000000 +0100
+++ gaim-0.58/src/protocols/oscar/im.c	2005-02-20 11:27:58.157004791 +0000
@@ -163,7 +163,7 @@
 		return -EINVAL;
 
 	if (args->flags & AIM_IMFLAGS_MULTIPART) {
-		if (args->mpmsg->numparts <= 0)
+		if (args->mpmsg->numparts == 0)
 			return -EINVAL;
 	} else {
 		if (!args->msg || (args->msglen <= 0))
@@ -1163,6 +1163,11 @@
 
 		/* Message string length, including character set info. */
 		msglen = aimbs_get16(&mbs);
+		if (msglen > aim_bstream_empty(&mbs))
+		{
+			faimdprintf(sess, 0, "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.");
+			break;
+		}
 
 		/* Character set info */
 		flag1 = aimbs_get16(&mbs);
@@ -1264,7 +1269,7 @@
 	aim_rxcallback_t userfunc;
 	int ret = 0;
 	struct aim_incomingim_ch1_args args;
-	int endpos;
+	unsigned int endpos;
 
 	memset(&args, 0, sizeof(args));
 
@@ -1275,11 +1280,17 @@
 	 * I've changed it to process the TLVs in-place.  This avoids lots
 	 * of per-IM memory allocations.
 	 */
-	while (aim_bstream_empty(bs)) {
-
+	while (aim_bstream_empty(bs))
+	{
 		type = aimbs_get16(bs);
 		length = aimbs_get16(bs);
 
+		if (length > aim_bstream_empty(bs))
+		{
+			faimdprintf(sess, 0, "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.\n", userinfo->sn);
+			break;
+		}
+
 		endpos = aim_bstream_curpos(bs) + length;
 
 		if (type == 0x0002) { /* Message Block */
@@ -1297,10 +1308,20 @@
 			aimbs_get8(bs); /* 01 */
 
 			args.featureslen = aimbs_get16(bs);
-			/* XXX XXX this is all evil! */
-			args.features = bs->data + bs->offset;
-			aim_bstream_advance(bs, args.featureslen);
-			args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES;
+			if (args.featureslen > aim_bstream_empty(bs))
+			{
+				faimdprintf(sess, 0, "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.\n", userinfo->sn);
+				break;
+			}
+			if (args.featureslen == 0)
+			{
+				args.features = NULL;
+			}
+			else
+			{
+				args.features = aimbs_getraw(bs, args.featureslen);
+				args.icbmflags |= AIM_IMFLAGS_CUSTOMFEATURES;
+			}
 
 			/*
 			 * The rest of the TLV contains one or more message
@@ -1347,8 +1368,17 @@
 
 		} else if (type == 0x0017) {
 
+			free(args.extdata);
 			args.extdatalen = length;
-			args.extdata = aimbs_getraw(bs, args.extdatalen);
+			if (args.extdatalen > aim_bstream_empty(bs))
+			{
+				faimdprintf(sess, 0, "Received an IM containing an invalid message part from %s.  They are probably trying to do something malicious.\n", userinfo->sn);
+				break;
+			}
+			if (args.extdatalen == 0)
+				args.extdata = NULL;
+			else
+				args.extdata = aimbs_getraw(bs, args.extdatalen);
 
 		} else {
 			faimdprintf(sess, 0, "incomingim_ch1: unknown TLV 0x%04x (len %d)\n", type, length);
@@ -1370,6 +1400,7 @@
 		ret = userfunc(sess, rx, channel, userinfo, &args);
 
 	aim_mpmsg_free(sess, &args.mpmsg);
+	free(args.features);
 	free(args.extdata);
 
 	return ret;
diff -Nur gaim-0.58~/src/protocols/oscar/rxqueue.c gaim-0.58/src/protocols/oscar/rxqueue.c
--- gaim-0.58~/src/protocols/oscar/rxqueue.c	2002-01-15 04:07:08.000000000 +0000
+++ gaim-0.58/src/protocols/oscar/rxqueue.c	2005-02-20 15:20:41.675720463 +0000
@@ -105,10 +105,15 @@
 	return;
 }
 
+/*
+ * N can be negative, which can be used for going backwards
+ * in a bstream.  I'm not sure if libfaim actually does
+ * this anywhere...
+ */
 faim_internal int aim_bstream_advance(aim_bstream_t *bs, int n)
 {
 
-	if (aim_bstream_empty(bs) < n)
+	if ((aim_bstream_curpos(bs) + n < 0) || (aim_bstream_empty(bs) < n))
 		return 0; /* XXX throw an exception */
 
 	bs->offset += n;
