mirror of
https://github.com/znc/znc.git
synced 2026-03-28 17:42:41 +01:00
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
This commit is contained in:
21
src/Chan.cpp
21
src/Chan.cpp
@@ -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 ");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user