From: <dat...@us...> - 2006-10-18 03:32:21
|
Revision: 17509 http://svn.sourceforge.net/gaim/?rev=17509&view=rev Author: datallah Date: 2006-10-17 20:32:14 -0700 (Tue, 17 Oct 2006) Log Message: ----------- Fix the situation (I think it will only happen while shutting down) where GaimBuddy->proto_data could be accessed after it is freed. Specifically, it happened when gtkblist was requesting the emblems from the msn prpl. Big thanks to henningn for noticing the funkiness in valgrind. I discovered that there is no function to retrieve all the buddies for an account (shock, horror) - so I modified gaim_find_buddies() to return all the account buddies if "name" is NULL. Modified Paths: -------------- trunk/libgaim/blist.c trunk/libgaim/blist.h trunk/libgaim/connection.c Modified: trunk/libgaim/blist.c =================================================================== --- trunk/libgaim/blist.c 2006-10-18 03:27:43 UTC (rev 17508) +++ trunk/libgaim/blist.c 2006-10-18 03:32:14 UTC (rev 17509) @@ -65,6 +65,11 @@ return gaim_blist_get_last_sibling(node->child); } +struct _list_account_buddies { + GSList *list; + GaimAccount *account; +}; + struct _gaim_hbuddy { char *name; GaimAccount *account; @@ -2119,26 +2124,46 @@ return ret; } +static void find_acct_buddies(gpointer key, gpointer value, gpointer data) +{ + struct _gaim_hbuddy *hb = key; + GaimBuddy *buddy = value; + struct _list_account_buddies *ab = data; + + if (hb->account == ab->account) { + ab->list = g_slist_prepend(ab->list, buddy); + } +} + GSList *gaim_find_buddies(GaimAccount *account, const char *name) { - struct buddy *buddy; - struct _gaim_hbuddy hb; + GaimBuddy *buddy; GaimBlistNode *node; GSList *ret = NULL; g_return_val_if_fail(gaimbuddylist != NULL, NULL); g_return_val_if_fail(account != NULL, NULL); - g_return_val_if_fail((name != NULL) && (*name != '\0'), NULL); - hb.name = g_strdup(gaim_normalize(account, name)); - hb.account = account; - for (node = gaimbuddylist->root; node != NULL; node = node->next) { - hb.group = node; - if ((buddy = g_hash_table_lookup(gaimbuddylist->buddies, &hb)) != NULL) - ret = g_slist_append(ret, buddy); + if ((name != NULL) && (*name != '\0')) { + struct _gaim_hbuddy hb; + + hb.name = g_strdup(gaim_normalize(account, name)); + hb.account = account; + + for (node = gaimbuddylist->root; node != NULL; node = node->next) { + hb.group = node; + if ((buddy = g_hash_table_lookup(gaimbuddylist->buddies, &hb)) != NULL) + ret = g_slist_prepend(ret, buddy); + } + g_free(hb.name); + } else { + struct _list_account_buddies *ab = g_new0(struct _list_account_buddies, 1); + ab->account = account; + g_hash_table_foreach(gaimbuddylist->buddies, find_acct_buddies, ab); + ret = ab->list; + g_free(ab); } - g_free(hb.name); return ret; } Modified: trunk/libgaim/blist.h =================================================================== --- trunk/libgaim/blist.h 2006-10-18 03:27:43 UTC (rev 17508) +++ trunk/libgaim/blist.h 2006-10-18 03:32:14 UTC (rev 17509) @@ -616,7 +616,7 @@ * Finds all GaimBuddy structs given a screenname and an account * * @param account The account this buddy belongs to - * @param name The buddy's screenname + * @param name The buddy's screenname (or NULL to return all buddies in the account) * * @return A GSList of buddies (which must be freed), or NULL if the buddy doesn't exist */ Modified: trunk/libgaim/connection.c =================================================================== --- trunk/libgaim/connection.c 2006-10-18 03:27:43 UTC (rev 17508) +++ trunk/libgaim/connection.c 2006-10-18 03:32:14 UTC (rev 17509) @@ -160,6 +160,7 @@ gaim_connection_destroy(GaimConnection *gc) { GaimAccount *account; + GSList *buddies, *tmp; #if 0 GList *wins; #endif @@ -195,6 +196,14 @@ (prpl_info->close)(gc); } + /* Clear out the proto data that was freed in the prpl close method*/ + buddies = gaim_find_buddies(account, NULL); + for (tmp = buddies; tmp; tmp = tmp->next) { + GaimBuddy *buddy = tmp->data; + buddy->proto_data = NULL; + } + g_slist_free(buddies); + connections = g_list_remove(connections, gc); gaim_connection_set_state(gc, GAIM_DISCONNECTED); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |