From 026b88e2fa4e7d70732507b1ae9b87eaa1a29873 Mon Sep 17 00:00:00 2001 From: MarkLee131 Date: Sat, 25 Apr 2026 10:34:06 +0800 Subject: [PATCH] ZNCString: avoid left shift of negative value in Base64Decode base64_table uses the sentinel 0xff for bytes outside the base64 alphabet. The old code read that through (char), producing signed -1, which made the three (c << N) expressions in Base64Decode undefined behaviour when the input contained any invalid byte. Keep c and c1 as unsigned char so the shifts are well-defined. Reachable pre-auth via CHTTPSock::ReadLine for the Authorization: Basic value. --- src/ZNCString.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/ZNCString.cpp b/src/ZNCString.cpp index abda9e83..cf9c28ca 100644 --- a/src/ZNCString.cpp +++ b/src/ZNCString.cpp @@ -1087,21 +1087,25 @@ unsigned long CString::Base64Decode(CString& sRet) const { sTmp.Replace("\n", ""); const char* in = sTmp.c_str(); - char c, c1, *p; + // Keep c and c1 unsigned so left-shifts are well-defined even when the + // input contains bytes outside the base64 alphabet (base64_table maps + // those to the sentinel 0xff, which used to become signed -1). + unsigned char c, c1; + char* p; unsigned long i; unsigned long uLen = sTmp.size(); char* out = new char[uLen + 1]{}; for (i = 0, p = out; i < uLen; i++) { - c = (char)base64_table[(unsigned char)in[i++]]; - c1 = (char)base64_table[(unsigned char)in[i++]]; + c = base64_table[(unsigned char)in[i++]]; + c1 = base64_table[(unsigned char)in[i++]]; *p++ = char((c << 2) | ((c1 >> 4) & 0x3)); if (i < uLen) { if (in[i] == '=') { break; } - c = (char)base64_table[(unsigned char)in[i]]; + c = base64_table[(unsigned char)in[i]]; *p++ = char(((c1 << 4) & 0xf0) | ((c >> 2) & 0xf)); } @@ -1110,7 +1114,7 @@ unsigned long CString::Base64Decode(CString& sRet) const { break; } *p++ = char(((c << 6) & 0xc0) | - (char)base64_table[(unsigned char)in[i]]); + base64_table[(unsigned char)in[i]]); } }