]> www.infradead.org Git - pidgin-chime.git/commitdiff
Fix crash when multiple conversations exist with the same peer email address
authorDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 14 Sep 2017 17:26:55 +0000 (10:26 -0700)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Thu, 14 Sep 2017 17:26:55 +0000 (10:26 -0700)
There can be more than one profile for a given email address. You can have
conversations with both profiles. I don't know how this happens, but I've
seen the aftermath.

This was causing the first 'im' structure to be destroyed when the second
was discovered, which caused a use-after-free because I haven't yet
converted the chime_im/chime_room/chime_msgs stuff to proper GOBjects
and refcounted them, and the fetch_messages call was still pending.

For a quick "fix", keep them around by having a hash table on profile_id
too.

chime.h
conversations.c

diff --git a/chime.h b/chime.h
index b5e161b7c901e92110860484e39dc4ce09046ad0..aac6d4d382ae56bb685af15a262b0b231faa84f6 100644 (file)
--- a/chime.h
+++ b/chime.h
@@ -33,6 +33,7 @@ struct purple_chime {
        ChimeConnection *cxn;
 
        GHashTable *ims_by_email;
+       GHashTable *ims_by_profile_id;
 
        GRegex *mention_regex;
        GHashTable *chats_by_room;
index e9c78d88305f5e664627ac88a730ec91c2376239..9d7b7fbfc7f181d5ac871a0ccd92b231810c9a52 100644 (file)
@@ -100,6 +100,7 @@ void on_chime_new_conversation(ChimeConnection *cxn, ChimeConversation *conv, Pu
        g_object_ref(im->peer);
 
        g_hash_table_insert(pc->ims_by_email, (void *)chime_contact_get_email(im->peer), im);
+       g_hash_table_insert(pc->ims_by_profile_id, (void *)chime_contact_get_profile_id(im->peer), im);
 
        g_signal_connect(conv, "typing", G_CALLBACK(on_conv_typing), im);
 
@@ -122,12 +123,14 @@ static void im_destroy(gpointer _im)
 
 void purple_chime_init_conversations(struct purple_chime *pc)
 {
-       pc->ims_by_email = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, im_destroy);
+       pc->ims_by_email = g_hash_table_new(g_str_hash, g_str_equal);
+       pc->ims_by_profile_id = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, im_destroy);
 }
 
 void purple_chime_destroy_conversations(struct purple_chime *pc)
 {
        g_clear_pointer(&pc->ims_by_email, g_hash_table_destroy);
+       g_clear_pointer(&pc->ims_by_profile_id, g_hash_table_destroy);
 }
 
 struct im_send_data {