diff --git a/Changes b/Changes index 02d920854..7e63893ed 100644 --- a/Changes +++ b/Changes @@ -8,12 +8,14 @@ Provided by Anope Dev. - 2005 Provided by nenolod. - 2005 02/03 A Support for Charybdis IRCd. [ #00] +02/12 F more va_list issues for 64bit platforms. [ #00] 01/15 F va_arg issue on various 64bit platforms. [#415] Provided by illu. - 2006 01/25 F Updated the french language file. [ #00] Provided by Trystan - 2006 +02/12 F Double unbanning of in certain conditions. [ #00] 01/25 F va_copy issue for various platforms. [ #00] diff --git a/src/actions.c b/src/actions.c index e9c70ae52..c9ca020a0 100644 --- a/src/actions.c +++ b/src/actions.c @@ -134,6 +134,7 @@ void common_unban(ChannelInfo * ci, char *nick) char *av[3], **bans; User *u; char *host; + int matchfound = 0; if (!ci || !ci->c || !nick) { return; @@ -158,19 +159,34 @@ void common_unban(ChannelInfo * ci, char *nick) anope_cmd_mode(whosends(ci), ci->name, "-b %s", bans[i]); av[2] = bans[i]; do_cmode(whosends(ci), 3, av); + matchfound++; } if (host) { - if (match_userip(bans[i], u, host)) { + /* prevent multiple unbans if the first one was successful in + locating the ban for us. This is due to match_userip() checks + the vhost again, and thus can return false positive results + for the function. but won't prevent thus from clearing out + the bans against an IP address since the first would fail and + the second would match - TSL + */ + if (!matchfound) { + if (match_userip(bans[i], u, host)) { anope_cmd_mode(whosends(ci), ci->name, "-b %s", bans[i]); av[2] = bans[i]; do_cmode(whosends(ci), 3, av); + } } } + matchfound = 0; } free(bans); free(av[1]); } + /* host_resolve() sstrdup us this info so we gotta free it */ + if (host) { + free(host); + } } /*************************************************************************/ diff --git a/src/slist.c b/src/slist.c index 81bd62ab0..a154cc47e 100644 --- a/src/slist.c +++ b/src/slist.c @@ -131,7 +131,7 @@ int slist_delete_range(SList * slist, char *range, slist_delcheckcb_t cb, ...) { int count = 0, i, n1, n2; - va_list args; + va_list args, preserve; va_start(args, cb); @@ -149,15 +149,26 @@ int slist_delete_range(SList * slist, char *range, slist_delcheckcb_t cb, } for (i = n1; i <= n2 && i > 0 && i <= slist->count; i++) { + if (!slist->list[i - 1]) continue; - if (cb && !cb(slist, slist->list[i - 1], args)) - return -1; + /* copy this off the stack for safety's sake --nenolod */ + VA_COPY(preserve, args); + + if (cb && !cb(slist, slist->list[i - 1], preserve)) { + va_end(preserve); + return -1; + } + + /* if it's to be freed, lets free it */ if (slist->opts && slist->opts->freeitem) slist->opts->freeitem(slist, slist->list[i - 1]); slist->list[i - 1] = NULL; + /* and release the copied list */ + va_end(preserve); + count++; } @@ -193,7 +204,7 @@ int slist_delete_range(SList * slist, char *range, slist_delcheckcb_t cb, int slist_enum(SList * slist, char *range, slist_enumcb_t cb, ...) { int count = 0, i, res; - va_list args; + va_list args, preserve; va_start(args, cb); @@ -204,9 +215,18 @@ int slist_enum(SList * slist, char *range, slist_enumcb_t cb, ...) continue; } - res = cb(slist, i + 1, slist->list[i], args); - if (res < 0) + /* copy off stack for safety */ + VA_COPY(preserve, args); + + res = cb(slist, i + 1, slist->list[i], preserve); + if (res < 0) { + va_end(preserve); break; + } + + /* and release our copy */ + va_end(preserve); + count += res; } } else { @@ -230,10 +250,18 @@ int slist_enum(SList * slist, char *range, slist_enumcb_t cb, ...) continue; } - res = cb(slist, i, slist->list[i - 1], args); - if (res < 0) + /* copy off stack for safety */ + VA_COPY(preserve, args); + + res = cb(slist, i, slist->list[i - 1], preserve); + if (res < 0) { + va_end(preserve); break; + } count += res; + + /* and release our copy */ + va_end(preserve); } if (res < -1) break;