diff --git a/src/Chan.cpp b/src/Chan.cpp index 93d67f30..1b824ceb 100644 --- a/src/Chan.cpp +++ b/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; diff --git a/test/IRCSockTest.cpp b/test/IRCSockTest.cpp index 0c208a83..3771105f 100644 --- a/test/IRCSockTest.cpp +++ b/test/IRCSockTest.cpp @@ -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 "); +}