1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-06-02 21:21:10 +00:00

Only handle MAM response if window still exists

Before this patch the following scenario lead to a segfault:
1. open a window that sends a MAM request
2. fast enough close that window again before the MAM response was
   processed
Once the MAM response is received we'd call `_mam_rsm_id_handler()`
from the `_iq_handler()` and `window` would point to a non-existant window
which leads to a segfault.

Signed-off-by: Steffen Jaeckel <jaeckel-floss@eyet-services.de>
This commit is contained in:
Steffen Jaeckel 2023-11-16 13:19:28 +01:00
parent 2b51675e89
commit c3ed0c3262
3 changed files with 55 additions and 0 deletions

View File

@ -712,6 +712,8 @@ ui_close_win(int index)
}
}
// remove the IQ handlers
iq_handlers_remove_win(window);
wins_close_by_num(index);
title_bar_console();
status_bar_current(1);

View File

@ -267,6 +267,54 @@ iq_handlers_init(void)
rooms_cache = g_hash_table_new_full(g_str_hash, g_str_equal, free, (GDestroyNotify)xmpp_stanza_release);
}
struct iq_win_finder
{
gsize max, cur;
char** to_be_removed;
};
static void
_win_find(char* key,
ProfIqHandler* handler,
struct iq_win_finder* finder)
{
if (handler->func == _mam_rsm_id_handler) {
if (finder->cur >= finder->max) {
finder->max *= 2;
finder->to_be_removed = g_realloc_n(finder->to_be_removed, finder->max, sizeof(char*));
}
finder->to_be_removed[finder->cur++] = g_strdup(key);
}
}
void
iq_handlers_remove_win(ProfWin* window)
{
log_debug("Remove window %p of type %d", window, window ? window->type : -1);
if (!window)
return;
GSList *cur = late_delivery_windows, *next;
while (cur) {
LateDeliveryUserdata* del_data = cur->data;
next = g_slist_next(cur);
if (del_data->win == (void*)window)
late_delivery_windows = g_slist_delete_link(late_delivery_windows,
cur);
cur = next;
}
struct iq_win_finder st = { 0 };
st.max = g_hash_table_size(id_handlers);
if (st.max == 0)
return;
st.to_be_removed = g_new(char*, st.max);
g_hash_table_foreach(id_handlers, (GHFunc)_win_find, &st);
for (gsize n = 0; n < st.cur; ++n) {
g_hash_table_remove(id_handlers, st.to_be_removed[n]);
g_free(st.to_be_removed[n]);
}
g_free(st.to_be_removed);
}
void
iq_handlers_clear()
{
@ -2696,6 +2744,10 @@ _mam_rsm_id_handler(xmpp_stanza_t* const stanza, void* const userdata)
gboolean is_complete = g_strcmp0(xmpp_stanza_get_attribute(fin, "complete"), "true") == 0;
MamRsmUserdata* data = (MamRsmUserdata*)userdata;
ProfWin* window = (ProfWin*)data->win;
if (wins_get_num(window) == -1) {
log_error("Window %p should not get any events anymore", window);
return 0;
}
buffer_remove_entry(window->layout->buffer, 0);

View File

@ -240,6 +240,7 @@ void iq_enable_carbons(void);
void iq_disable_carbons(void);
void iq_send_software_version(const char* const fulljid);
void iq_rooms_cache_clear(void);
void iq_handlers_remove_win(ProfWin* window);
void iq_handlers_clear();
void iq_room_list_request(gchar* conferencejid, gchar* filter);
void iq_disco_info_request(gchar* jid);