Commit 16c849da authored by Alexey Sokolov's avatar Alexey Sokolov

Fix crash when parsing incorrect channel modes sent by server.

Sometimes certain servers don't send a argument for modes which it
declared as ones which need an argument.

No released version is affected.

Close #1684
parent b8b62a14
......@@ -300,7 +300,8 @@ void CChan::OnWho(const CString& sNick, const CString& sIdent,
}
}
void CChan::ModeChange(const CString& sModes, const VCString& vsModes, const CNick* pOpNick) {
void CChan::ModeChange(const CString& sModes, const VCString& vsModes,
const CNick* pOpNick) {
bool bAdd = true;
/* Try to find a CNick* from this channel so that pOpNick->HasPerm()
......@@ -319,6 +320,13 @@ void CChan::ModeChange(const CString& sModes, const VCString& vsModes, const CNi
}
VCString::const_iterator argIter = vsModes.begin();
const CString sEmpty;
auto nextArg = [&]() -> const CString& {
if (argIter == vsModes.end()) {
return sEmpty;
}
return *argIter++;
};
for (unsigned int a = 0; a < sModes.size(); a++) {
const char& cMode = sModes[a];
......@@ -327,11 +335,10 @@ void CChan::ModeChange(const CString& sModes, const VCString& vsModes, const CNi
} else if (cMode == '-') {
bAdd = false;
} else if (m_pNetwork->GetIRCSock()->IsPermMode(cMode)) {
CString sArg = *argIter++;
const CString& sArg = nextArg();
CNick* pNick = FindNick(sArg);
if (pNick) {
char cPerm =
m_pNetwork->GetIRCSock()->GetPermFromMode(cMode);
char cPerm = m_pNetwork->GetIRCSock()->GetPermFromMode(cMode);
if (cPerm) {
bool bNoChange = (pNick->HasPerm(cPerm) == bAdd);
......@@ -389,16 +396,16 @@ void CChan::ModeChange(const CString& sModes, const VCString& vsModes, const CNi
switch (m_pNetwork->GetIRCSock()->GetModeType(cMode)) {
case CIRCSock::ListArg:
bList = true;
sArg = *argIter++;
sArg = nextArg();
break;
case CIRCSock::HasArg:
sArg = *argIter++;
sArg = nextArg();
break;
case CIRCSock::NoArg:
break;
case CIRCSock::ArgWhenSet:
if (bAdd) {
sArg = *argIter++;
sArg = nextArg();
}
break;
......
......@@ -331,7 +331,8 @@ TEST_F(IRCSockTest, OnPartMessage) {
}
TEST_F(IRCSockTest, StatusModes) {
m_pTestSock->ReadLine(":server 005 user PREFIX=(Yohv)!@%+ :are supported by this server");
m_pTestSock->ReadLine(
":server 005 user PREFIX=(Yohv)!@%+ :are supported by this server");
EXPECT_TRUE(m_pTestSock->IsPermMode('Y'));
EXPECT_TRUE(m_pTestSock->IsPermMode('o'));
......@@ -547,3 +548,13 @@ TEST_F(IRCSockTest, StatusMsg) {
EXPECT_EQ(m_pTestChan->GetBuffer().GetLine(0, *m_pTestClient),
":someone PRIVMSG @#chan :hello ops");
}
TEST_F(IRCSockTest, ChanMode) {
// https://github.com/znc/znc/issues/1684
m_pTestSock->ReadLine(
":irc.znc.in 001 me :Welcome to the Internet Relay Network me");
m_pTestSock->ReadLine(
":irc.znc.in 005 me CHANMODES=be,f,lj,nti "
":are supported by this server");
m_pTestSock->ReadLine(":irc.znc.in 324 me #chan +ntf ");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment