]> jfr.im git - irc/znc/znc.git/commitdiff
Fix crash when parsing incorrect channel modes sent by server.
authorAlexey Sokolov <redacted>
Thu, 7 Nov 2019 08:36:41 +0000 (08:36 +0000)
committerAlexey Sokolov <redacted>
Thu, 7 Nov 2019 08:36:41 +0000 (08:36 +0000)
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

src/Chan.cpp
test/IRCSockTest.cpp

index 93d67f306f5adbfc4fda56852891255025ddc6bf..1b824cebdc4432ef256d601fd4ab4826e5fb500d 100644 (file)
@@ -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;
index 0c208a83fbbede28b4613d23c59d875366b2dfaa..3771105f24015e3628936b7a6142d997f737aa34 100644 (file)
@@ -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 ");
+}