summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Catanzaro <mcatanzaro@gnome.org>2020-09-24 07:03:10 -0500
committerAlexander Akulich <akulichalexander@gmail.com>2020-11-01 01:12:41 +0300
commit6967ca8e1f8d8f7948a430fea0bf159e126042be (patch)
tree76ed6f56dd5ac1d17f4515b7eee3225577d1e135
parent3f04a0d60fdc653bffd6919cb374a8d496771a8e (diff)
downloadtelepathy-idle-6967ca8e1f8d8f7948a430fea0bf159e126042be.tar.gz
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
-rw-r--r--src/idle-parser.c26
1 files 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) {