diff --git a/src/butil/third_party/modp_b64/modp_b64_rvv.cc b/src/butil/third_party/modp_b64/modp_b64_rvv.cc index 10fd8847dd..4c76177918 100644 --- a/src/butil/third_party/modp_b64/modp_b64_rvv.cc +++ b/src/butil/third_party/modp_b64/modp_b64_rvv.cc @@ -150,11 +150,14 @@ size_t rvv_modp_b64_decode(char* dest, const char* src, size_t len) { if (len == 0) return 0; - /* Strip trailing '=' padding (up to 2 chars for valid base64) */ - while (len > 0 && src[len-1] == '=') { - len--; + /* Match the padded scalar decoder's length and padding rules. */ + if (len < 4 || len % 4 != 0) return MODP_B64_RVV_ERROR; + if (src[len-1] == '=') { + --len; + if (src[len-1] == '=') { + --len; + } } - if (len == 0) return 0; size_t i = 0; uint8_t* p = (uint8_t*)dest; diff --git a/test/base64_unittest.cc b/test/base64_unittest.cc index 40a3906a97..3f49642315 100644 --- a/test/base64_unittest.cc +++ b/test/base64_unittest.cc @@ -24,4 +24,16 @@ TEST(Base64Test, Basic) { EXPECT_EQ(kText, decoded); } +TEST(Base64Test, RejectsMalformedPaddingAndLengths) { + for (const char* input : {"A", "AA", "AAA", "AAAAA", "=", "====", + "A===", "AA======", "AA=A", "AA==AAAA"}) { + std::string decoded; + EXPECT_FALSE(butil::Base64Decode(input, &decoded)) << input; + } + for (const char* input : {"", "AA==", "AAA=", "AAAA"}) { + std::string decoded; + EXPECT_TRUE(butil::Base64Decode(input, &decoded)) << input; + } +} + } // namespace butil