Skip to content

Commit 64613bc

Browse files
committed
Don't crash if user specified invalid encoding.
This is CVE-2019-9917
1 parent 46544d9 commit 64613bc

File tree

5 files changed

+34
-9
lines changed

5 files changed

+34
-9
lines changed

Diff for: modules/controlpanel.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ class CAdminMod : public CModule {
495495
#ifdef HAVE_ICU
496496
else if (sVar == "clientencoding") {
497497
pUser->SetClientEncoding(sValue);
498-
PutModule("ClientEncoding = " + sValue);
498+
PutModule("ClientEncoding = " + pUser->GetClientEncoding());
499499
}
500500
#endif
501501
else

Diff for: src/IRCNetwork.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1482,9 +1482,9 @@ void CIRCNetwork::SetBindHost(const CString& s) {
14821482
}
14831483

14841484
void CIRCNetwork::SetEncoding(const CString& s) {
1485-
m_sEncoding = s;
1485+
m_sEncoding = CZNC::Get().FixupEncoding(s);
14861486
if (GetIRCSock()) {
1487-
GetIRCSock()->SetEncoding(s);
1487+
GetIRCSock()->SetEncoding(m_sEncoding);
14881488
}
14891489
}
14901490

Diff for: src/User.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1253,9 +1253,9 @@ void CUser::SetAdmin(bool b) { m_bAdmin = b; }
12531253
void CUser::SetDenySetBindHost(bool b) { m_bDenySetBindHost = b; }
12541254
void CUser::SetDefaultChanModes(const CString& s) { m_sDefaultChanModes = s; }
12551255
void CUser::SetClientEncoding(const CString& s) {
1256-
m_sClientEncoding = s;
1256+
m_sClientEncoding = CZNC::Get().FixupEncoding(s);
12571257
for (CClient* pClient : GetAllClients()) {
1258-
pClient->SetEncoding(s);
1258+
pClient->SetEncoding(m_sClientEncoding);
12591259
}
12601260
}
12611261
void CUser::SetQuitMsg(const CString& s) { m_sQuitMsg = s; }

Diff for: src/znc.cpp

+22-4
Original file line numberDiff line numberDiff line change
@@ -2092,18 +2092,36 @@ void CZNC::ForceEncoding() {
20922092
m_uiForceEncoding++;
20932093
#ifdef HAVE_ICU
20942094
for (Csock* pSock : GetManager()) {
2095-
if (pSock->GetEncoding().empty()) {
2096-
pSock->SetEncoding("UTF-8");
2097-
}
2095+
pSock->SetEncoding(FixupEncoding(pSock->GetEncoding()));
20982096
}
20992097
#endif
21002098
}
21012099
void CZNC::UnforceEncoding() { m_uiForceEncoding--; }
21022100
bool CZNC::IsForcingEncoding() const { return m_uiForceEncoding; }
21032101
CString CZNC::FixupEncoding(const CString& sEncoding) const {
2104-
if (sEncoding.empty() && m_uiForceEncoding) {
2102+
if (!m_uiForceEncoding) {
2103+
return sEncoding;
2104+
}
2105+
if (sEncoding.empty()) {
2106+
return "UTF-8";
2107+
}
2108+
const char* sRealEncoding = sEncoding.c_str();
2109+
if (sEncoding[0] == '*' || sEncoding[0] == '^') {
2110+
sRealEncoding++;
2111+
}
2112+
if (!*sRealEncoding) {
21052113
return "UTF-8";
21062114
}
2115+
#ifdef HAVE_ICU
2116+
UErrorCode e = U_ZERO_ERROR;
2117+
UConverter* cnv = ucnv_open(sRealEncoding, &e);
2118+
if (cnv) {
2119+
ucnv_close(cnv);
2120+
}
2121+
if (U_FAILURE(e)) {
2122+
return "UTF-8";
2123+
}
2124+
#endif
21072125
return sEncoding;
21082126
}
21092127

Diff for: test/integration/tests/scripting.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ TEST_F(ZNCTest, Modpython) {
5555
ircd.Write(":n!u@h PRIVMSG nick :Hi\xF0, github issue #1229");
5656
// "replacement character"
5757
client.ReadUntil("Hi\xEF\xBF\xBD, github issue");
58+
59+
// Non-existing encoding
60+
client.Write("PRIVMSG *controlpanel :Set ClientEncoding $me Western");
61+
client.Write("JOIN #a\342");
62+
client.ReadUntil(
63+
":*controlpanel!znc@znc.in PRIVMSG nick :ClientEncoding = UTF-8");
64+
ircd.ReadUntil("JOIN #a\xEF\xBF\xBD");
5865
}
5966

6067
TEST_F(ZNCTest, ModpythonSocket) {

0 commit comments

Comments
 (0)