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