Skip to content

Commit

Permalink
Only handle MAM response if window still exists
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
sjaeckel committed Dec 9, 2023
1 parent f003667 commit 6116702
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/ui/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
52 changes: 52 additions & 0 deletions src/xmpp/iq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions src/xmpp/xmpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 6116702

Please sign in to comment.