summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/common/hexchat.c2
-rw-r--r--src/common/plugin.c48
2 files changed, 39 insertions, 11 deletions
diff --git a/src/common/hexchat.c b/src/common/hexchat.c
index 8702c63d..9be2e56d 100644
--- a/src/common/hexchat.c
+++ b/src/common/hexchat.c
@@ -191,7 +191,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 *
diff --git a/src/common/plugin.c b/src/common/plugin.c
index 40e55bbf..d3f3b7ca 100644
--- a/src/common/plugin.c
+++ b/src/common/plugin.c
@@ -574,10 +574,13 @@ static int
 plugin_hook_run (session *sess, char *name, char *word[], char *word_eol[],
 				 hexchat_event_attrs *attrs, int type)
 {
+	/* 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)
 	{
@@ -623,18 +626,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;
@@ -687,6 +694,18 @@ plugin_emit_print (session *sess, char *word[], time_t server_time)
 							HOOK_PRINT | HOOK_PRINT_ATTRS);
 }
 
+/* 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)
 {
@@ -697,7 +716,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);
+
+	/* 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