diff options
-rw-r--r-- | src/common/hexchat.c | 6 | ||||
-rw-r--r-- | src/common/plugin.c | 77 | ||||
-rw-r--r-- | src/common/plugin.h | 2 | ||||
-rw-r--r-- | src/fe-gtk/maingui.c | 6 |
4 files changed, 64 insertions, 27 deletions
diff --git a/src/common/hexchat.c b/src/common/hexchat.c index 3ba7ed6d..f74fe489 100644 --- a/src/common/hexchat.c +++ b/src/common/hexchat.c @@ -183,7 +183,7 @@ lastact_getfirst(int (*filter) (session *sess)) int is_session (session * sess) { - return g_slist_find (sess_list, sess) ? 1 : 0; + return sess != NULL && (g_slist_find (sess_list, sess) ? 1 : 0); } session * @@ -552,7 +552,7 @@ new_ircwindow (server *serv, char *name, int type, int focus) if (user && user->hostname) set_topic (sess, user->hostname, user->hostname); } - plugin_emit_dummy_print (sess, "Open Context"); + plugin_emit_dummy_print (sess, "Open Context", -1); return sess; } @@ -629,7 +629,7 @@ session_free (session *killsess) GSList *list; int oldidx; - plugin_emit_dummy_print (killsess, "Close Context"); + plugin_emit_dummy_print (killsess, "Close Context", 0); if (current_tab == killsess) current_tab = NULL; diff --git a/src/common/plugin.c b/src/common/plugin.c index 40e55bbf..5524e984 100644 --- a/src/common/plugin.c +++ b/src/common/plugin.c @@ -572,12 +572,15 @@ plugin_hook_find (GSList *list, int type, char *name) static int plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], - hexchat_event_attrs *attrs, int type) + hexchat_event_attrs *attrs, int type, int mask) { + /* fix segfault https://github.com/hexchat/hexchat/issues/2265 */ + static int depth = 0; GSList *list, *next; hexchat_hook *hook; int ret, eat = 0; + depth++; list = hook_list; while (1) { @@ -609,6 +612,11 @@ plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], break; } + if ((ret & mask) != ret) { + g_critical("plugin tried to eat cleanup hooks"); + } + ret &= mask; + if ((ret & HEXCHAT_EAT_HEXCHAT) && (ret & HEXCHAT_EAT_PLUGIN)) { eat = 1; @@ -623,18 +631,22 @@ plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[], } xit: - /* really remove deleted hooks now */ - list = hook_list; - while (list) + depth--; + if (!depth) { - hook = list->data; - next = list->next; - if (!hook || hook->type == HOOK_DELETED) + /* really remove deleted hooks now */ + list = hook_list; + while (list) { - hook_list = g_slist_remove (hook_list, hook); - g_free (hook); + hook = list->data; + next = list->next; + if (!hook || hook->type == HOOK_DELETED) + { + hook_list = g_slist_remove (hook_list, hook); + g_free (hook); + } + list = next; } - list = next; } return eat; @@ -645,7 +657,7 @@ xit: int plugin_emit_command (session *sess, char *name, char *word[], char *word_eol[]) { - return plugin_hook_run (sess, name, word, word_eol, NULL, HOOK_COMMAND); + return plugin_hook_run (sess, name, word, word_eol, NULL, HOOK_COMMAND, -1); } hexchat_event_attrs * @@ -671,7 +683,7 @@ plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[], attrs.server_time_utc = server_time; return plugin_hook_run (sess, name, word, word_eol, &attrs, - HOOK_SERVER | HOOK_SERVER_ATTRS); + HOOK_SERVER | HOOK_SERVER_ATTRS, -1); } /* see if any plugins are interested in this print event */ @@ -684,11 +696,23 @@ plugin_emit_print (session *sess, char *word[], time_t server_time) attrs.server_time_utc = server_time; return plugin_hook_run (sess, word[0], word, NULL, &attrs, - HOOK_PRINT | HOOK_PRINT_ATTRS); + HOOK_PRINT | HOOK_PRINT_ATTRS, -1); +} + +/* used by plugin_emit_dummy_print to fix some UB */ +static void +check_and_invalidate(void *plug_, void *killsess_) +{ + hexchat_plugin *plug = plug_; + session *killsess = killsess_; + if (plug->context == killsess) + { + plug->context = NULL; + } } int -plugin_emit_dummy_print (session *sess, char *name) +plugin_emit_dummy_print (session *sess, char *name, int mask) { char *word[PDIWORDS]; int i; @@ -697,7 +721,16 @@ plugin_emit_dummy_print (session *sess, char *name) for (i = 1; i < PDIWORDS; i++) word[i] = "\000"; - return plugin_hook_run (sess, name, word, NULL, NULL, HOOK_PRINT); + i = plugin_hook_run (sess, name, word, NULL, NULL, HOOK_PRINT, mask); + + /* shoehorned fix for Undefined Behaviour */ + /* see https://stackoverflow.com/q/52628773/3691554 */ + /* this needs to be done on the hexchat side */ + if (strcmp(name, "Close Context") == 0) { + g_slist_foreach(plugin_list, &check_and_invalidate, sess); + } + + return i; } int @@ -730,7 +763,7 @@ plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, gu for (i = 5; i < PDIWORDS; i++) word[i] = "\000"; - return plugin_hook_run (sess, word[0], word, NULL, NULL, HOOK_PRINT); + return plugin_hook_run (sess, word[0], word, NULL, NULL, HOOK_PRINT, -1); } static int @@ -1121,12 +1154,16 @@ hexchat_get_context (hexchat_plugin *ph) int hexchat_set_context (hexchat_plugin *ph, hexchat_context *context) { - if (is_session (context)) + if (context == NULL) { + return 0; + } + if (!is_session (context)) { - ph->context = context; - return 1; + g_critical("plugin tried to set an invalid context"); + return 0; } - return 0; + ph->context = context; + return 1; } hexchat_context * diff --git a/src/common/plugin.h b/src/common/plugin.h index fb7da831..051d1f5a 100644 --- a/src/common/plugin.h +++ b/src/common/plugin.h @@ -174,7 +174,7 @@ int plugin_emit_command (session *sess, char *name, char *word[], char *word_eol int plugin_emit_server (session *sess, char *name, char *word[], char *word_eol[], time_t server_time); int plugin_emit_print (session *sess, char *word[], time_t server_time); -int plugin_emit_dummy_print (session *sess, char *name); +int plugin_emit_dummy_print (session *sess, char *name, int mask); int plugin_emit_keypress (session *sess, unsigned int state, unsigned int keyval, gunichar key); GList* plugin_command_list(GList *tmp_list); int plugin_show_help (session *sess, char *cmd); diff --git a/src/fe-gtk/maingui.c b/src/fe-gtk/maingui.c index 61f59856..3e62da15 100644 --- a/src/fe-gtk/maingui.c +++ b/src/fe-gtk/maingui.c @@ -963,7 +963,7 @@ mg_populate (session *sess) mg_set_topic_tip (sess); - plugin_emit_dummy_print (sess, "Focus Tab"); + plugin_emit_dummy_print (sess, "Focus Tab", -1); } void @@ -3081,7 +3081,7 @@ mg_tabwin_focus_cb (GtkWindow * win, GdkEventFocus *event, gpointer userdata) if (current_sess) { gtk_xtext_check_marker_visibility (GTK_XTEXT (current_sess->gui->xtext)); - plugin_emit_dummy_print (current_sess, "Focus Window"); + plugin_emit_dummy_print (current_sess, "Focus Window", -1); } unflash_window (GTK_WIDGET (win)); return FALSE; @@ -3095,7 +3095,7 @@ mg_topwin_focus_cb (GtkWindow * win, GdkEventFocus *event, session *sess) sess->server->server_session = sess; gtk_xtext_check_marker_visibility(GTK_XTEXT (current_sess->gui->xtext)); unflash_window (GTK_WIDGET (win)); - plugin_emit_dummy_print (sess, "Focus Window"); + plugin_emit_dummy_print (sess, "Focus Window", -1); return FALSE; } |