diff --git a/src/google/protobuf/compiler/cpp/extension.cc b/src/google/protobuf/compiler/cpp/extension.cc index 6dab8fdb96c47..0babdcf46a07e 100644 --- a/src/google/protobuf/compiler/cpp/extension.cc +++ b/src/google/protobuf/compiler/cpp/extension.cc @@ -69,6 +69,12 @@ ExtensionGenerator::ExtensionGenerator(const FieldDescriptor* descriptor, variables_["constant_name"] = FieldConstantName(descriptor_); variables_["field_type"] = absl::StrCat(static_cast(descriptor_->type())); + // Downgrade string to bytes if it is not UTF8 validated. + if (descriptor_->type() == FieldDescriptor::TYPE_STRING && + !descriptor_->requires_utf8_validation()) { + variables_["field_type"] = + absl::StrCat(static_cast(FieldDescriptor::TYPE_BYTES)); + } variables_["repeated"] = descriptor_->is_repeated() ? "true" : "false"; variables_["packed"] = descriptor_->is_packed() ? "true" : "false"; variables_["dllexport_decl"] = options.dllexport_decl; diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc index f7d2d5a72a754..2f1bdffdba3e5 100644 --- a/src/google/protobuf/generated_message_reflection.cc +++ b/src/google/protobuf/generated_message_reflection.cc @@ -2182,7 +2182,10 @@ void Reflection::AddString(Message* message, const FieldDescriptor* field, std::string value) const { USAGE_MUTABLE_CHECK_ALL(AddString, REPEATED, STRING); if (field->is_extension()) { - MutableExtensionSet(message)->AddString(field->number(), field->type(), + MutableExtensionSet(message)->AddString(field->number(), + field->requires_utf8_validation() + ? FieldDescriptor::TYPE_STRING + : FieldDescriptor::TYPE_BYTES, std::move(value), field); } else { switch (field->cpp_string_type()) { diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc index d13e79ddba231..6f579d4329f2c 100644 --- a/src/google/protobuf/generated_message_reflection_unittest.cc +++ b/src/google/protobuf/generated_message_reflection_unittest.cc @@ -38,6 +38,7 @@ #include "google/protobuf/message.h" #include "google/protobuf/port.h" #include "google/protobuf/test_util.h" +#include "google/protobuf/text_format.h" #include "google/protobuf/unittest.pb.h" #include "google/protobuf/unittest_mset.pb.h" #include "google/protobuf/unittest_mset_wire_format.pb.h" @@ -1807,6 +1808,22 @@ TEST(GeneratedMessageReflection, SwapImplicitPresenceShouldWork) { EXPECT_EQ(lhs.child().optional_int32(), -1); } +TEST(GeneratedMessageReflection, UnvalidatedStringsAreDowngradedToBytes) { + protobuf_unittest::TestChildExtension parsed_msg; + google::protobuf::TextFormat::ParseFromString( + R"pb( + optional_extension < + [protobuf_unittest.repeated_string_extension]: "foo" + > + )pb", + &parsed_msg); + protobuf_unittest::TestChildExtension msg; + msg.mutable_optional_extension()->AddExtension( + protobuf_unittest::repeated_string_extension, "bar"); + parsed_msg.mutable_optional_extension()->Swap( + msg.mutable_optional_extension()); +} + } // namespace } // namespace protobuf } // namespace google diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto index 3f1aa841ddc06..19f01da2392f8 100644 --- a/src/google/protobuf/unittest.proto +++ b/src/google/protobuf/unittest.proto @@ -500,6 +500,13 @@ extend TestAllExtensions { TestAllTypes.NestedMessage oneof_nested_message_extension = 112; string oneof_string_extension = 113; bytes oneof_bytes_extension = 114; + + string optional_utf8_string_extension = 115 [ + features.utf8_validation = VERIFY + ]; + repeated string repeated_utf8_string_extension = 116 [ + features.utf8_validation = VERIFY + ]; } message OptionalGroup_extension {