diff options
author | Adam <Adam@anope.org> | 2014-03-04 04:14:17 -0500 |
---|---|---|
committer | Adam <Adam@anope.org> | 2014-03-04 04:15:32 -0500 |
commit | 09bec79b473fad40268f7b25b92c4979563829c4 (patch) | |
tree | e5e70c2fd3c6bfbcdb3fbd571c3c0191741b3caa | |
parent | 55a5affcb8251c6ef677d78ea848dc8d26b90471 (diff) |
Fix 2 crashes from removing the permanent channel mode from channels which do not exist
-rw-r--r-- | include/modules.h | 2 | ||||
-rw-r--r-- | modules/commands/cs_mode.cpp | 4 | ||||
-rw-r--r-- | modules/commands/cs_set.cpp | 6 | ||||
-rw-r--r-- | modules/pseudoclients/chanserv.cpp | 5 | ||||
-rw-r--r-- | src/channels.cpp | 16 |
5 files changed, 21 insertions, 12 deletions
diff --git a/include/modules.h b/include/modules.h index 5bfb1e8e2..0d121089a 100644 --- a/include/modules.h +++ b/include/modules.h @@ -1010,7 +1010,7 @@ class CoreExport Module : public Extensible * mostly to ensure mlock/+r are set. * @param c The channel */ - virtual void OnCheckModes(Channel *c) { throw NotImplementedException(); } + virtual void OnCheckModes(Reference<Channel> &c) { throw NotImplementedException(); } /** Called when a channel is synced. * Channels are synced after a sjoin is finished processing diff --git a/modules/commands/cs_mode.cpp b/modules/commands/cs_mode.cpp index db5eecbb3..a13610d23 100644 --- a/modules/commands/cs_mode.cpp +++ b/modules/commands/cs_mode.cpp @@ -902,9 +902,9 @@ class CSMode : public Module } } - void OnCheckModes(Channel *c) anope_override + void OnCheckModes(Reference<Channel> &c) anope_override { - if (!c->ci) + if (!c || !c->ci) return; ModeLocks *locks = modelocks.Get(c->ci); diff --git a/modules/commands/cs_set.cpp b/modules/commands/cs_set.cpp index bb8232808..1109c888e 100644 --- a/modules/commands/cs_set.cpp +++ b/modules/commands/cs_set.cpp @@ -1289,12 +1289,6 @@ class CSSet : public Module { if (c->ci) persist.Unset(c->ci); - - if (c->CheckDelete()) - { - delete c; - return EVENT_STOP; - } } if (c->ci && mode->type != MODE_STATUS && !c->syncing && Me->IsSynced()) diff --git a/modules/pseudoclients/chanserv.cpp b/modules/pseudoclients/chanserv.cpp index 388a14649..250296f55 100644 --- a/modules/pseudoclients/chanserv.cpp +++ b/modules/pseudoclients/chanserv.cpp @@ -274,8 +274,11 @@ class ChanServCore : public Module, public ChanServService "lists and settings for any channel.")); } - void OnCheckModes(Channel *c) anope_override + void OnCheckModes(Reference<Channel> &c) anope_override { + if (!c) + return; + if (c->ci) c->SetMode(c->ci->WhoSends(), "REGISTERED", "", false); else diff --git a/src/channels.cpp b/src/channels.cpp index a9ad68b93..86c261029 100644 --- a/src/channels.cpp +++ b/src/channels.cpp @@ -111,7 +111,8 @@ void Channel::CheckModes() return; } - FOREACH_MOD(OnCheckModes, (this)); + Reference<Channel> ref = this; + FOREACH_MOD(OnCheckModes, (ref)); } bool Channel::CheckDelete() @@ -371,6 +372,15 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *cm, const A FOREACH_RESULT(OnChannelModeUnset, MOD_RESULT, (this, setter, cm, param)); + if (cm->name == "PERM") + { + if (this->CheckDelete()) + { + delete this; + return; + } + } + /* Check for mlock */ if (!enforce_mlock || MOD_RESULT == EVENT_STOP) return; @@ -505,9 +515,11 @@ void Channel::SetModes(BotInfo *bi, bool enforce_mlock, const char *cmodes, ...) vsnprintf(buf, BUFSIZE - 1, cmodes, args); va_end(args); + Reference<Channel> this_reference(this); + spacesepstream sep(buf); sep.GetToken(modebuf); - for (unsigned i = 0, end = modebuf.length(); i < end; ++i) + for (unsigned i = 0, end = modebuf.length(); this_reference && i < end; ++i) { ChannelMode *cm; |