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;