From 562420555b90b6725341e4e9fadd72e7fd924706 Mon Sep 17 00:00:00 2001 From: Michael Poole Date: Sat, 18 Dec 2004 04:41:07 +0000 Subject: [PATCH] Fix bugs and memory leaks in ban management. git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@1279 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 15 +++++++++++++++ include/channel.h | 2 +- ircd/channel.c | 35 ++++++++++++++--------------------- ircd/m_silence.c | 2 +- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index c03c937..a1f65fe 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2004-12-17 Michael Poole + + * ircd/channel.h (apply_ban): Add new flag to indicate whether + newban should be free()'d after it is used. + + * ircd/channel.c (apply_ban): Likewise. Also set BAN_DEL flag + when setting BAN_OVERLAPPED, and free newban when BAN_DEL. + (mode_parse_ban): Delete buggy shortcut when channel banlist is + empty. + (mode_process_bans): Always give ownership of ban->banstr to the + mode buffer, avoiding a memory leak. + + * ircd/m_silence.c (apply_silence): Pass new parameter to + apply_ban. + 2004-12-17 Michael Poole * ircd/channel.c (sub1_from_channel): Immediately destroy diff --git a/include/channel.h b/include/channel.h index f939738..24e70b4 100644 --- a/include/channel.h +++ b/include/channel.h @@ -456,7 +456,7 @@ extern void joinbuf_join(struct JoinBuf *jbuf, struct Channel *chan, extern int joinbuf_flush(struct JoinBuf *jbuf); extern struct Ban *make_ban(const char *banstr); extern struct Ban *find_ban(struct Client *cptr, struct Ban *banlist); -extern int apply_ban(struct Ban **banlist, struct Ban *newban); +extern int apply_ban(struct Ban **banlist, struct Ban *newban, int free); extern void free_ban(struct Ban *ban); #endif /* INCLUDED_channel_h */ diff --git a/ircd/channel.c b/ircd/channel.c index ca5bde2..b335f93 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -2683,7 +2683,7 @@ bmatch(struct Ban *old_ban, struct Ban *new_ban) * @param[in] newban Ban (or exception) to add (or remove). * @return Zero if \a newban could be applied, non-zero if not. */ -int apply_ban(struct Ban **banlist, struct Ban *newban) +int apply_ban(struct Ban **banlist, struct Ban *newban, int free) { struct Ban *ban; size_t count = 0; @@ -2694,7 +2694,8 @@ int apply_ban(struct Ban **banlist, struct Ban *newban) /* If a less specific entry is found, fail. */ for (ban = *banlist; ban; ban = ban->next) { if (!bmatch(ban, newban)) { - free_ban(newban); + if (free) + free_ban(newban); return 1; } if (!(ban->flags & (BAN_OVERLAPPED|BAN_DEL))) { @@ -2705,7 +2706,7 @@ int apply_ban(struct Ban **banlist, struct Ban *newban) /* Mark more specific entries and add this one to the end of the list. */ while ((ban = *banlist) != NULL) { if (!bmatch(newban, ban)) { - ban->flags |= BAN_OVERLAPPED; + ban->flags |= BAN_OVERLAPPED | BAN_DEL; } banlist = &ban->next; } @@ -2716,16 +2717,16 @@ int apply_ban(struct Ban **banlist, struct Ban *newban) /* Mark more specific entries. */ for (ban = *banlist; ban; ban = ban->next) { if (!bmatch(newban, ban)) { - ban->flags |= BAN_OVERLAPPED; + ban->flags |= BAN_OVERLAPPED | BAN_DEL; remove_count++; } } - /* If no matches were found, fail. */ - if (!remove_count) { + if (free) free_ban(newban); - return 3; - } - return 0; + else + MyFree(newban->banstr); + /* If no matches were found, fail. */ + return remove_count ? 0 : 3; } free_ban(newban); return 4; @@ -2738,7 +2739,7 @@ static void mode_parse_ban(struct ParseState *state, int *flag_p) { char *t_str, *s; - struct Ban *ban, *newban = 0; + struct Ban *ban, *newban; if (state->parc <= 0) { /* Not enough args, send ban list */ if (MyUser(state->sptr) && !(state->done & DONE_BANLIST)) { @@ -2772,12 +2773,6 @@ mode_parse_ban(struct ParseState *state, int *flag_p) return; } - if (!state->chptr->banlist) { - state->chptr->banlist = newban; /* add our ban with its flags */ - state->done |= DONE_BANCLEAN; - return; - } - /* Clear all ADD/DEL/OVERLAPPED flags from ban list. */ if (!(state->done & DONE_BANCLEAN)) { for (ban = state->chptr->banlist; ban; ban = ban->next) @@ -2794,7 +2789,7 @@ mode_parse_ban(struct ParseState *state, int *flag_p) set_ban_mask(newban, collapse(pretty_mask(t_str))); newban->who = cli_name(state->sptr); newban->when = TStime(); - apply_ban(&state->chptr->banlist, newban); + apply_ban(&state->chptr->banlist, newban, 0); } /* @@ -2829,8 +2824,7 @@ mode_process_bans(struct ParseState *state) continue; } else if (ban->flags & BAN_DEL) { /* Deleted a ban? */ modebuf_mode_string(state->mbuf, MODE_DEL | MODE_BAN, - ban->banstr, - state->flags & MODE_PARSE_SET); + ban->banstr, 1); if (state->flags & MODE_PARSE_SET) { /* Ok, make it take effect */ if (prevban) /* clip it out of the list... */ @@ -2873,8 +2867,7 @@ mode_process_bans(struct ParseState *state) } else { /* add the ban to the buffer */ modebuf_mode_string(state->mbuf, MODE_ADD | MODE_BAN, - ban->banstr, - !(state->flags & MODE_PARSE_SET)); + ban->banstr, 1); if (state->flags & MODE_PARSE_SET) { /* create a new ban */ newban = make_ban(ban->banstr); diff --git a/ircd/m_silence.c b/ircd/m_silence.c index 7a78d14..1be8a4b 100644 --- a/ircd/m_silence.c +++ b/ircd/m_silence.c @@ -86,7 +86,7 @@ apply_silence(struct Client *sptr, const char *mask) /* Make the silence, set flags, and apply it. */ sile = make_ban(mask); sile->flags |= flags; - return apply_ban(&cli_user(sptr)->silence, sile) ? NULL : sile; + return apply_ban(&cli_user(sptr)->silence, sile, 1) ? NULL : sile; } /** Apply and send silence updates for a user. -- 2.20.1