Fix DecodeBase64 to reject truncated input

If the input doesn't have the proper number of encoding characters
(a multiple of 4), return an empty result.

Co-Authored-By: Sean Curtis <sean.curtis@tri.global>
This commit is contained in:
Jeremy Nimmer
2026-02-10 07:01:22 -08:00
committed by Jesse Beder
parent 2e6383d272
commit 80ea0028c7
2 changed files with 16 additions and 3 deletions

View File

@@ -74,7 +74,8 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
unsigned char *out = &ret[0]; unsigned char *out = &ret[0];
unsigned value = 0; unsigned value = 0;
for (std::size_t i = 0, cnt = 0; i < input.size(); i++) { std::size_t cnt = 0;
for (std::size_t i = 0; i < input.size(); i++) {
if (std::isspace(static_cast<unsigned char>(input[i]))) { if (std::isspace(static_cast<unsigned char>(input[i]))) {
// skip newlines // skip newlines
continue; continue;
@@ -84,14 +85,20 @@ std::vector<unsigned char> DecodeBase64(const std::string &input) {
return ret_type(); return ret_type();
value = (value << 6) | d; value = (value << 6) | d;
if (cnt % 4 == 3) { if (cnt == 3) {
*out++ = value >> 16; *out++ = value >> 16;
if (i > 0 && input[i - 1] != '=') if (i > 0 && input[i - 1] != '=')
*out++ = value >> 8; *out++ = value >> 8;
if (input[i] != '=') if (input[i] != '=')
*out++ = value; *out++ = value;
cnt = 0;
} else {
++cnt;
} }
++cnt; }
if (cnt != 0) {
// An invalid number of characters were encountered.
return ret_type();
} }
ret.resize(out - &ret[0]); ret.resize(out - &ret[0]);

View File

@@ -12,3 +12,9 @@ TEST(BinaryTest, DecodingNoCrashOnNegative) {
const std::vector<unsigned char> &result = YAML::DecodeBase64(input); const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
EXPECT_TRUE(result.empty()); EXPECT_TRUE(result.empty());
} }
TEST(BinaryTest, DecodingTooShort) {
std::string input{90, 71, 86, 104, 90, 71, 74, 108, 90, 87, 89};
const std::vector<unsigned char> &result = YAML::DecodeBase64(input);
EXPECT_TRUE(result.empty());
}