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.
This commit is contained in:
MarkLee131
2026-04-25 10:34:06 +08:00
parent 8566db72dd
commit 026b88e2fa
+9 -5
View File
@@ -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]]);
}
}