8d4e70d
From 0be57b4f449ce9289734f630873391ef1831dd3c Mon Sep 17 00:00:00 2001
8d4e70d
From: Michael Catanzaro <mcatanzaro@gnome.org>
8d4e70d
Date: Thu, 24 Sep 2020 07:03:10 -0500
8d4e70d
Subject: [PATCH] Properly handle long IRC messages
8d4e70d
8d4e70d
IRC messages are delimited by CRLF. When the string passed to
8d4e70d
idle_parser_receive() doesn't end in \r or \n, the remaining parts get
8d4e70d
stashed away to be used to form a message on the next call to
8d4e70d
idle_parser_receive(). But telepathy-idle improperly assumes that the
8d4e70d
next call to idle_parser_receive() will definitely contain \r or \n,
8d4e70d
i.e. it assumes that an IRC message cannot be split between three calls
8d4e70d
to idle_parser_receive(). That assumption is wrong.
8d4e70d
8d4e70d
Fixes polari#147
8d4e70d
---
8d4e70d
 src/idle-parser.c | 26 +++++++++++++++++++++-----
8d4e70d
 1 file changed, 21 insertions(+), 5 deletions(-)
8d4e70d
8d4e70d
diff --git a/src/idle-parser.c b/src/idle-parser.c
8d4e70d
index 159e6cc..71ca8b1 100644
8d4e70d
--- a/src/idle-parser.c
8d4e70d
+++ b/src/idle-parser.c
8d4e70d
@@ -151,6 +151,7 @@ struct _IdleParserPrivate {
8d4e70d
 
8d4e70d
 	/* continuation line buffer */
8d4e70d
 	gchar split_buf[IRC_MSG_MAXLEN + 3];
8d4e70d
+	guint split_buf_used;
8d4e70d
 
8d4e70d
 	/* message handlers */
8d4e70d
 	GSList *handlers[IDLE_PARSER_LAST_MESSAGE_CODE];
8d4e70d
@@ -226,6 +227,13 @@ strnlen(const char *msg, size_t maxlen)
8d4e70d
 }
8d4e70d
 #endif
8d4e70d
 
8d4e70d
+static void clear_split_buf(IdleParser *parser) {
8d4e70d
+	IdleParserPrivate *priv = IDLE_PARSER_GET_PRIVATE(parser);
8d4e70d
+
8d4e70d
+	memset(priv->split_buf, '\0', IRC_MSG_MAXLEN + 3);
8d4e70d
+	priv->split_buf_used = 0;
8d4e70d
+}
8d4e70d
+
8d4e70d
 void idle_parser_receive(IdleParser *parser, const gchar *msg) {
8d4e70d
 	IdleParserPrivate *priv = IDLE_PARSER_GET_PRIVATE(parser);
8d4e70d
 	guint i;
8d4e70d
@@ -245,7 +253,7 @@ void idle_parser_receive(IdleParser *parser, const gchar *msg) {
8d4e70d
 				if ((lasti == 0) && (priv->split_buf[0] != '\0')) {
8d4e70d
 					g_strlcpy(g_stpcpy(concat_buf, priv->split_buf), msg, i + 1);
8d4e70d
 					tmp = concat_buf;
8d4e70d
-					memset(priv->split_buf, '\0', IRC_MSG_MAXLEN + 3);
8d4e70d
+					clear_split_buf(parser);
8d4e70d
 				} else {
8d4e70d
 					tmp = g_strndup(msg + lasti, i - lasti);
8d4e70d
 				}
8d4e70d
@@ -264,10 +272,18 @@ void idle_parser_receive(IdleParser *parser, const gchar *msg) {
8d4e70d
 		}
8d4e70d
 	}
8d4e70d
 
8d4e70d
-	if (!line_ends)
8d4e70d
-		g_strlcpy(priv->split_buf, msg + lasti, (IRC_MSG_MAXLEN + 3) - lasti);
8d4e70d
-	else
8d4e70d
-		memset(priv->split_buf, '\0', IRC_MSG_MAXLEN + 3);
8d4e70d
+	if (!line_ends) {
8d4e70d
+		len = strlen(msg + lasti);
8d4e70d
+		if (len > (IRC_MSG_MAXLEN + 3) - priv->split_buf_used - 1) {
8d4e70d
+			IDLE_DEBUG("Discarding content that exceeds maximum message length: \"%s\"", msg + lasti);
8d4e70d
+			clear_split_buf(parser);
8d4e70d
+		} else {
8d4e70d
+			g_strlcpy(priv->split_buf + priv->split_buf_used, msg + lasti, (IRC_MSG_MAXLEN + 3) - priv->split_buf_used);
8d4e70d
+			priv->split_buf_used += len;
8d4e70d
+		}
8d4e70d
+	} else {
8d4e70d
+		clear_split_buf(parser);
8d4e70d
+	}
8d4e70d
 }
8d4e70d
 
8d4e70d
 void idle_parser_add_handler(IdleParser *parser, IdleParserMessageCode code, IdleParserMessageHandler handler, gpointer user_data) {
8d4e70d
-- 
8d4e70d
GitLab
8d4e70d