summary refs log tree commit diff stats
path: root/src/common/proto-irc.c
diff options
context:
space:
mode:
authorPatrick Griffis <tingping@tingping.se>2018-03-04 12:14:09 -0500
committerPatrick Griffis <tingping@tingping.se>2018-03-04 12:38:57 -0500
commitf6333b592b0d574d68e96d04a09a6cae956ee6c3 (patch)
tree2e15f237b53200d04c767401a451a47b5aca8573 /src/common/proto-irc.c
parent6e4fc09ce005db965523ef8930ea51ca429815a2 (diff)
Fix out of bounds read when DCC message sender contains quotes
This cannot be triggered by any user generally.

Fixes #2128
Diffstat (limited to 'src/common/proto-irc.c')
-rw-r--r--src/common/proto-irc.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/common/proto-irc.c b/src/common/proto-irc.c
index 969ac2e4..e055c7e2 100644
--- a/src/common/proto-irc.c
+++ b/src/common/proto-irc.c
@@ -1241,15 +1241,36 @@ process_named_msg (session *sess, char *type, char *word[], char *word_eol[],
 					len = strlen (text);
 					if (text[0] == 1 && text[len - 1] == 1)	/* ctcp */
 					{
+						char *new_pdibuf = NULL;
 						text[len - 1] = 0;
 						text++;
 						if (g_ascii_strncasecmp (text, "ACTION", 6) != 0)
 							flood_check (nick, ip, serv, sess, 0);
 						if (g_ascii_strncasecmp (text, "DCC ", 4) == 0)
-							/* redo this with handle_quotes TRUE */
-							process_data_init (word[1], word_eol[1], word, word_eol, TRUE, FALSE);
+						{
+							int i;
+							char *new_word[PDIWORDS+1] = { NULL };
+							char *new_word_eol[PDIWORDS+1] = { NULL };
+
+							new_pdibuf = g_malloc (strlen (word_eol[6]) + 1);
+
+							/* This is a bit ugly but we handle the contents of the DCC message containing
+							 * "quoted paths for files" here which means reparsing the message with handle_quotes.
+							 * We avoid reparsing the entire message to avoid corrupting the non DCC parts.
+							 * Greater than PDIWORD length DCC messages will be truncated. */
+							process_data_init (new_pdibuf, word_eol[6], new_word, new_word_eol, TRUE, FALSE);
+							for (i = 6; i < PDIWORDS; ++i)
+							{
+								word[i] = new_word[i - 5];
+								word_eol[i] = new_word_eol[i - 5];
+							}
+						}
+
 						ctcp_handle (sess, to, nick, ip, text, word, word_eol, id,
 										 tags_data);
+
+						/* Note word will be invalid beyond this scope */
+						g_free (new_pdibuf);
 					} else
 					{
 						if (is_channel (serv, to))