summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam <Adam@anope.org>2014-03-04 04:14:17 -0500
committerAdam <Adam@anope.org>2014-03-04 04:15:32 -0500
commit09bec79b473fad40268f7b25b92c4979563829c4 (patch)
treee5e70c2fd3c6bfbcdb3fbd571c3c0191741b3caa
parent55a5affcb8251c6ef677d78ea848dc8d26b90471 (diff)
Fix 2 crashes from removing the permanent channel mode from channels which do not exist
-rw-r--r--include/modules.h2
-rw-r--r--modules/commands/cs_mode.cpp4
-rw-r--r--modules/commands/cs_set.cpp6
-rw-r--r--modules/pseudoclients/chanserv.cpp5
-rw-r--r--src/channels.cpp16
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;