From f4396c4d16f67cb28effd86a636b9db8fa48821c Mon Sep 17 00:00:00 2001 From: dequis Date: Sat, 5 Dec 2015 21:43:14 -0300 Subject: irc_send_names: refactor to use GString instead of the stack Because modifying this code was making me REALLY uncomfortable. This still only allocates memory once. Needing to extend the string would be a bug in the length checks, but at least that's harmless now. --- irc_send.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'irc_send.c') diff --git a/irc_send.c b/irc_send.c index af432d4d..954c5322 100644 --- a/irc_send.c +++ b/irc_send.c @@ -201,34 +201,41 @@ void irc_send_kick(irc_channel_t *ic, irc_user_t *iu, irc_user_t *kicker, const kicker->host, ic->name, iu->nick, reason ? : ""); } +#define IRC_NAMES_LEN 385 + void irc_send_names(irc_channel_t *ic) { GSList *l; - char namelist[385] = ""; + GString *namelist = g_string_sized_new(IRC_NAMES_LEN); /* RFCs say there is no error reply allowed on NAMES, so when the channel is invalid, just give an empty reply. */ for (l = ic->users; l; l = l->next) { irc_channel_user_t *icu = l->data; irc_user_t *iu = icu->iu; + size_t extra_len = strlen(iu->nick); + char prefix; - if (strlen(namelist) + strlen(iu->nick) > sizeof(namelist) - 4) { - irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist); - *namelist = 0; + if (namelist->len + extra_len > IRC_NAMES_LEN - 4) { + irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist->str); + g_string_truncate(namelist, 0); } - namelist[strlen(namelist) + 1] = '\0'; - namelist[strlen(namelist)] = irc_channel_user_get_prefix(icu); + if ((prefix = irc_channel_user_get_prefix(icu))) { + g_string_append_c(namelist, prefix); + } - strcat(namelist, iu->nick); - strcat(namelist, " "); + g_string_append(namelist, iu->nick); + g_string_append_c(namelist, ' '); } - if (*namelist) { - irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist); + if (namelist->len) { + irc_send_num(ic->irc, 353, "= %s :%s", ic->name, namelist->str); } irc_send_num(ic->irc, 366, "%s :End of /NAMES list", ic->name); + + g_string_free(namelist, TRUE); } void irc_send_topic(irc_channel_t *ic, gboolean topic_change) -- cgit v1.2.3