From 7b7f6912131d02b032e3c5f01ea6fd4ba567f7e9 Mon Sep 17 00:00:00 2001 From: Alexey Sokolov Date: Mon, 23 Jun 2025 22:41:08 +0100 Subject: [PATCH] Don't store "this" in static variable Fix #1960 This could also cause use-after-free if the first connected socket disconnects --- src/IRCSock.cpp | 30 ++++++++++++++++++------------ test/integration/tests/core.cpp | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/IRCSock.cpp b/src/IRCSock.cpp index 37f3b9d5..b9ce227c 100644 --- a/src/IRCSock.cpp +++ b/src/IRCSock.cpp @@ -408,22 +408,28 @@ bool CIRCSock::OnCapabilityMessage(CMessage& Message) { sArgs = Message.GetParam(2); } - static std::map> mSupportedCaps = { - {"multi-prefix", [this](bool bVal) { m_bNamesx = bVal; }}, - {"userhost-in-names", [this](bool bVal) { m_bUHNames = bVal; }}, - {"cap-notify", [](bool bVal) {}}, - {"invite-notify", [](bool bVal) {}}, - {"server-time", [this](bool bVal) { m_bServerTime = bVal; }}, - {"znc.in/server-time-iso", [this](bool bVal) { m_bServerTime = bVal; }}, - {"chghost", [](bool) {}}, - {"message-tags", [this](bool bVal) { m_bMessageTagCap = bVal; }}, - }; + static std::map> + mSupportedCaps = { + {"multi-prefix", + [](CIRCSock* pSock, bool bVal) { pSock->m_bNamesx = bVal; }}, + {"userhost-in-names", + [](CIRCSock* pSock, bool bVal) { pSock->m_bUHNames = bVal; }}, + {"cap-notify", [](CIRCSock* pSock, bool bVal) {}}, + {"invite-notify", [](CIRCSock* pSock, bool bVal) {}}, + {"server-time", + [](CIRCSock* pSock, bool bVal) { pSock->m_bServerTime = bVal; }}, + {"znc.in/server-time-iso", + [](CIRCSock* pSock, bool bVal) { pSock->m_bServerTime = bVal; }}, + {"chghost", [](CIRCSock* pSock, bool) {}}, + {"message-tags", [](CIRCSock* pSock, + bool bVal) { pSock->m_bMessageTagCap = bVal; }}, + }; auto RemoveCap = [&](const CString& sCap) { IRCSOCKMODULECALL(OnServerCapResult(sCap, false), NOTHING); auto it = mSupportedCaps.find(sCap); if (it != mSupportedCaps.end()) { - it->second(false); + it->second(this, false); } m_ssAcceptedCaps.erase(sCap); m_ssPendingCaps.erase(sCap); @@ -457,7 +463,7 @@ bool CIRCSock::OnCapabilityMessage(CMessage& Message) { IRCSOCKMODULECALL(OnServerCapResult(sCap, true), NOTHING); auto it = mSupportedCaps.find(sCap); if (it != mSupportedCaps.end()) { - it->second(true); + it->second(this, true); } m_ssAcceptedCaps.insert(std::move(sCap)); } diff --git a/test/integration/tests/core.cpp b/test/integration/tests/core.cpp index 2bef8b67..9e1171d0 100644 --- a/test/integration/tests/core.cpp +++ b/test/integration/tests/core.cpp @@ -1191,5 +1191,24 @@ TEST_F(ZNCTest, JoinWhileRegistration) { ircd.ReadUntil("JOIN #foo"); } +TEST_F(ZNCTest, Issue1960) { + auto znc = Run(); + auto ircd1 = ConnectIRCd(); + auto client = LoginClient(); + ircd1.Write("CAP user ACK :message-tags"); + ircd1.Write(":server 001 nick :Hello"); + ircd1.Write(":server 005 nick blahblah"); + client.ReadUntil("blahblah"); + client.Write("znc addnetwork second"); + client.Write("znc jumpnetwork second"); + client.Write("znc addserver unix:" + m_dir.path().toUtf8() + "/inttest.ircd"); + auto ircd2 = ConnectIRCd(); + ircd2.Write("CAP user ACK :message-tags"); + ircd2.Write(":server 001 nick :Hello"); + client.ReadUntil("Connected"); + client.Write("@foo TAGMSG #bar"); + ircd2.ReadUntil("@foo TAGMSG #bar"); +} + } // namespace } // namespace znc_inttest