mirror of
https://github.com/anope/anope.git
synced 2026-07-03 09:53:12 +02:00
Change Channel::GetModeList to return a copy of the mode list, not a
pair of lower/upper bound iterators. Sometimes when iterating the list, like in cs_mode, we can modify the contents of it, which combined with mlock always agressively trying to readd modes to it can do bad things.
This commit is contained in:
+25
-20
@@ -202,9 +202,9 @@ size_t Channel::HasMode(const Anope::string &mname, const Anope::string ¶m)
|
||||
{
|
||||
if (param.empty())
|
||||
return modes.count(mname);
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(mname);
|
||||
for (; its.first != its.second; ++its.first)
|
||||
if (its.first->second.equals_ci(param))
|
||||
std::vector<Anope::string> v = this->GetModeList(mname);
|
||||
for (unsigned int i = 0; i < v.size(); ++i)
|
||||
if (v[i].equals_ci(param))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -240,12 +240,20 @@ const Channel::ModeList &Channel::GetModes() const
|
||||
return this->modes;
|
||||
}
|
||||
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> Channel::GetModeList(const Anope::string &mname)
|
||||
template<typename F, typename S>
|
||||
struct second
|
||||
{
|
||||
Channel::ModeList::iterator it = this->modes.find(mname), it_end = it;
|
||||
if (it != this->modes.end())
|
||||
it_end = this->modes.upper_bound(mname);
|
||||
return std::make_pair(it, it_end);
|
||||
S operator()(const std::pair<F, S> &p)
|
||||
{
|
||||
return p.second;
|
||||
}
|
||||
};
|
||||
|
||||
std::vector<Anope::string> Channel::GetModeList(const Anope::string &mname)
|
||||
{
|
||||
std::vector<Anope::string> r;
|
||||
std::transform(modes.lower_bound(mname), modes.upper_bound(mname), std::back_inserter(r), second<Anope::string, Anope::string>());
|
||||
return r;
|
||||
}
|
||||
|
||||
void Channel::SetModeInternal(MessageSource &setter, ChannelMode *ocm, const Anope::string &oparam, bool enforce_mlock)
|
||||
@@ -363,11 +371,10 @@ void Channel::RemoveModeInternal(MessageSource &setter, ChannelMode *ocm, const
|
||||
|
||||
if (cm->type == MODE_LIST)
|
||||
{
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> its = this->GetModeList(cm->name);
|
||||
for (; its.first != its.second; ++its.first)
|
||||
if (param.equals_ci(its.first->second))
|
||||
for (Channel::ModeList::iterator it = modes.lower_bound(cm->name), it_end = modes.upper_bound(cm->name); it != it_end; ++it)
|
||||
if (param.equals_ci(it->second))
|
||||
{
|
||||
this->modes.erase(its.first);
|
||||
this->modes.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -715,11 +722,10 @@ bool Channel::MatchesList(User *u, const Anope::string &mode)
|
||||
if (!this->HasMode(mode))
|
||||
return false;
|
||||
|
||||
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> m = this->GetModeList(mode);
|
||||
for (; m.first != m.second; ++m.first)
|
||||
std::vector<Anope::string> v = this->GetModeList(mode);
|
||||
for (unsigned i = 0; i < v.size(); ++i)
|
||||
{
|
||||
Entry e(mode, m.first->second);
|
||||
Entry e(mode, v[i]);
|
||||
if (e.Matches(u))
|
||||
return true;
|
||||
}
|
||||
@@ -872,11 +878,10 @@ bool Channel::Unban(User *u, const Anope::string &mode, bool full)
|
||||
|
||||
bool ret = false;
|
||||
|
||||
std::pair<Channel::ModeList::iterator, Channel::ModeList::iterator> bans = this->GetModeList(mode);
|
||||
for (; bans.first != bans.second;)
|
||||
std::vector<Anope::string> v = this->GetModeList(mode);
|
||||
for (unsigned int i = 0; i < v.size(); ++i)
|
||||
{
|
||||
Entry ban(mode, bans.first->second);
|
||||
++bans.first;
|
||||
Entry ban(mode, v[i]);
|
||||
if (ban.Matches(u, full))
|
||||
{
|
||||
this->RemoveMode(NULL, mode, ban.GetMask());
|
||||
|
||||
Reference in New Issue
Block a user