From 694b5c9f874d7337cd2e03761e0de435275dd64d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Helleu?= Date: Fri, 14 Feb 2020 08:11:02 +0100 Subject: [PATCH] irc: fix crash when a new message 005 is received with longer nick prefixes Thanks to Stuart Nevans Locke for reporting the issue. --- ChangeLog.adoc | 1 + src/plugins/irc/irc-nick.c | 47 ++++++++++++++++++++++++++++++++++++ src/plugins/irc/irc-nick.h | 2 ++ src/plugins/irc/irc-server.c | 13 +++++++++- 4 files changed, 62 insertions(+), 1 deletion(-) diff --git a/ChangeLog.adoc b/ChangeLog.adoc index c33ee80ac..d5be7e151 100644 --- a/ChangeLog.adoc +++ b/ChangeLog.adoc @@ -20,6 +20,7 @@ https://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] Bug fixes:: + * irc: fix crash when a new message 005 is received with longer nick prefixes * irc: fix crash when receiving a malformed message 324 (channel mode) (CVE-2020-8955) [[v2.7]] diff --git a/src/plugins/irc/irc-nick.c b/src/plugins/irc/irc-nick.c index 57bb1d601..765a39e59 100644 --- a/src/plugins/irc/irc-nick.c +++ b/src/plugins/irc/irc-nick.c @@ -643,6 +643,53 @@ irc_nick_set_mode (struct t_irc_server *server, struct t_irc_channel *channel, } } +/* + * Reallocates the "prefixes" string in all nicks of all channels on the server + * (after 005 has been received). + */ + +void +irc_nick_realloc_prefixes (struct t_irc_server *server, + int old_length, int new_length) +{ + struct t_irc_channel *ptr_channel; + struct t_irc_nick *ptr_nick; + char *new_prefixes; + + for (ptr_channel = server->channels; ptr_channel; + ptr_channel = ptr_channel->next_channel) + { + for (ptr_nick = ptr_channel->nicks; ptr_nick; + ptr_nick = ptr_nick->next_nick) + { + if (ptr_nick->prefixes) + { + new_prefixes = realloc (ptr_nick->prefixes, new_length + 1); + if (new_prefixes) + { + ptr_nick->prefixes = new_prefixes; + if (new_length > old_length) + { + memset (ptr_nick->prefixes + old_length, + ' ', + new_length - old_length); + } + ptr_nick->prefixes[new_length] = '\0'; + } + } + else + { + ptr_nick->prefixes = malloc (new_length + 1); + if (ptr_nick->prefixes) + { + memset (ptr_nick->prefixes, ' ', new_length); + ptr_nick->prefixes[new_length] = '\0'; + } + } + } + } +} + /* * Removes a nick from a channel. */ diff --git a/src/plugins/irc/irc-nick.h b/src/plugins/irc/irc-nick.h index 52316891d..1d5b2914d 100644 --- a/src/plugins/irc/irc-nick.h +++ b/src/plugins/irc/irc-nick.h @@ -74,6 +74,8 @@ extern void irc_nick_change (struct t_irc_server *server, extern void irc_nick_set_mode (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick, int set, char mode); +extern void irc_nick_realloc_prefixes (struct t_irc_server *server, + int old_length, int new_length); extern void irc_nick_free (struct t_irc_server *server, struct t_irc_channel *channel, struct t_irc_nick *nick); diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index 828924fab..0e0624afa 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -988,11 +988,15 @@ irc_server_set_prefix_modes_chars (struct t_irc_server *server, const char *prefix) { char *pos; - int i, length_modes, length_chars; + int i, old_length_chars, length_modes, length_chars; if (!server || !prefix) return; + old_length_chars = (server->prefix_chars) ? + strlen (server->prefix_chars) : + strlen (irc_server_prefix_chars_default); + /* free previous values */ if (server->prefix_modes) { @@ -1032,6 +1036,13 @@ irc_server_set_prefix_modes_chars (struct t_irc_server *server, } } } + + length_chars = (server->prefix_chars) ? + strlen (server->prefix_chars) : + strlen (irc_server_prefix_chars_default); + + if (length_chars != old_length_chars) + irc_nick_realloc_prefixes (server, old_length_chars, length_chars); } /*