Mercurial > pidgin.yaz
changeset 30174:b0bc67f42027
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.
author | Elliott Sales de Andrade <qulogic@pidgin.im> |
---|---|
date | Tue, 20 Apr 2010 00:05:34 +0000 |
parents | 4ebecacf2fbb |
children | 57a482217ee1 |
files | libpurple/protocols/msn/msn.c libpurple/protocols/msn/slplink.c libpurple/protocols/msn/slplink.h |
diffstat | 3 files changed, 46 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- 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; }
--- 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;
--- 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); /**