# HG changeset patch # User Elliott Sales de Andrade # Date 1271721934 0 # Node ID b0bc67f42027703670c8bd39d01e4f7baf612f59 # Parent 4ebecacf2fbb22c022411655b2b337abbbce6738 Fix a possible use-after-free. If the user initiated a file transfer while a display pic transfer was in progress, and that transfer finished before the user selected a file, then the MsnSlpLink to that user could be used after it's freed. Also, if there were a conversation open to that user, then the slplink would not be freed, so the FT must be started from the buddy list. Fixes #6453. diff -r 4ebecacf2fbb -r b0bc67f42027 libpurple/protocols/msn/msn.c --- a/libpurple/protocols/msn/msn.c Mon Apr 19 23:55:03 2010 +0000 +++ b/libpurple/protocols/msn/msn.c Tue Apr 20 00:05:34 2010 +0000 @@ -589,6 +589,14 @@ { MsnSlpLink *slplink = xfer->data; msn_slplink_request_ft(slplink, xfer); + msn_slplink_unref(slplink); +} + +static void +t_msn_xfer_cancel_send(PurpleXfer *xfer) +{ + MsnSlpLink *slplink = xfer->data; + msn_slplink_unref(slplink); } static PurpleXfer* @@ -603,9 +611,10 @@ g_return_val_if_fail(xfer != NULL, NULL); - xfer->data = msn_session_get_slplink(session, who); + xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who)); purple_xfer_set_init_fnc(xfer, t_msn_xfer_init); + purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send); return xfer; } diff -r 4ebecacf2fbb -r b0bc67f42027 libpurple/protocols/msn/slplink.c --- a/libpurple/protocols/msn/slplink.c Mon Apr 19 23:55:03 2010 +0000 +++ b/libpurple/protocols/msn/slplink.c Tue Apr 20 00:05:34 2010 +0000 @@ -78,7 +78,7 @@ session->slplinks = g_list_append(session->slplinks, slplink); - return slplink; + return msn_slplink_ref(slplink); } void @@ -94,6 +94,11 @@ if (slplink->swboard != NULL) slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink); + if (slplink->refs > 1) { + slplink->refs--; + return; + } + session = slplink->session; #if 0 @@ -115,6 +120,31 @@ } MsnSlpLink * +msn_slplink_ref(MsnSlpLink *slplink) +{ + g_return_val_if_fail(slplink != NULL, NULL); + + slplink->refs++; + if (purple_debug_is_verbose()) + purple_debug_info("msn", "slplink ref (%p)[%d]\n", slplink, slplink->refs); + + return slplink; +} + +void +msn_slplink_unref(MsnSlpLink *slplink) +{ + g_return_if_fail(slplink != NULL); + + slplink->refs--; + if (purple_debug_is_verbose()) + purple_debug_info("msn", "slplink unref (%p)[%d]\n", slplink, slplink->refs); + + if (slplink->refs == 0) + msn_slplink_destroy(slplink); +} + +MsnSlpLink * msn_session_find_slplink(MsnSession *session, const char *who) { GList *l; diff -r 4ebecacf2fbb -r b0bc67f42027 libpurple/protocols/msn/slplink.h --- a/libpurple/protocols/msn/slplink.h Mon Apr 19 23:55:03 2010 +0000 +++ b/libpurple/protocols/msn/slplink.h Tue Apr 20 00:05:34 2010 +0000 @@ -43,6 +43,8 @@ MsnSession *session; MsnSwitchBoard *swboard; + int refs; + char *remote_user; int slp_seq_id; @@ -55,6 +57,9 @@ GQueue *slp_msg_queue; }; +MsnSlpLink *msn_slplink_ref(MsnSlpLink *slplink); +void msn_slplink_unref(MsnSlpLink *slplink); + void msn_slplink_destroy(MsnSlpLink *slplink); /**