[cpp] Adjust base64 padding parsing in TJSONProtocol
diff --git a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
index a04d7ad..ba20f91 100644
--- a/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
+++ b/lib/cpp/src/thrift/protocol/TJSONProtocol.cpp
@@ -811,11 +811,10 @@
auto len = static_cast<uint32_t>(tmp.length());
str.clear();
// Ignore padding
- if (len >= 2) {
- uint32_t bound = len - 2;
- for (uint32_t i = len - 1; i >= bound && b[i] == '='; --i) {
- --len;
- }
+ uint32_t padding_count = 0;
+ while (len > 0 && b[len - 1] == '=' && padding_count < 2) {
+ --len;
+ ++padding_count;
}
while (len >= 4) {
base64_decode(b, 4);
diff --git a/lib/cpp/test/JSONProtoTest.cpp b/lib/cpp/test/JSONProtoTest.cpp
index 1874ccd..fd5a8d1 100644
--- a/lib/cpp/test/JSONProtoTest.cpp
+++ b/lib/cpp/test/JSONProtoTest.cpp
@@ -379,3 +379,26 @@
BOOST_CHECK_THROW(ooe2.read(proto.get()),
apache::thrift::protocol::TProtocolException);
}
+
+BOOST_AUTO_TEST_CASE(test_json_base64_padding_validation) {
+ auto test_base64_padding = [](const std::string& base64_value) {
+ std::string json_string = "{\"11\":{\"str\":\"" + base64_value + "\"}}";
+ std::shared_ptr<TMemoryBuffer> buffer(new TMemoryBuffer(
+ (uint8_t*)(json_string.c_str()), static_cast<uint32_t>(json_string.size())));
+ std::shared_ptr<TJSONProtocol> proto(new TJSONProtocol(buffer));
+
+ OneOfEach ooe;
+ BOOST_CHECK_NO_THROW(ooe.read(proto.get()));
+ };
+
+ // Valid base64 with 1 padding character
+ test_base64_padding("QWE=");
+ // Valid base64 with 2 padding characters
+ test_base64_padding("QQ==");
+ // Just padding
+ test_base64_padding("=");
+ test_base64_padding("==");
+ // Malformed base64 with excessive padding (processed conservatively)
+ test_base64_padding("===");
+ test_base64_padding("====");
+}