Migrate C++ utf8 validation to a global feature.

PiperOrigin-RevId: 568686594
pull/14191/head
Mike Kruskal 1 year ago committed by Copybara-Service
parent 06310353a2
commit e9fc181ae9
  1. 27
      src/google/protobuf/compiler/cpp/generator.cc
  2. 82
      src/google/protobuf/compiler/cpp/generator_unittest.cc
  3. 26
      src/google/protobuf/descriptor.cc
  4. 177
      src/google/protobuf/descriptor_unittest.cc
  5. 8
      src/google/protobuf/editions/golden/compare_cpp_codegen_failure.txt
  6. 2
      src/google/protobuf/editions/golden/compare_cpp_codegen_failure.xml
  7. 2
      src/google/protobuf/editions/golden/editions_transform_proto2.proto
  8. 2
      src/google/protobuf/editions/golden/editions_transform_proto2_lite.proto
  9. 10
      src/google/protobuf/editions/golden/editions_transform_proto2_utf8_disabled.proto
  10. 6
      src/google/protobuf/editions/golden/editions_transform_proto3.proto
  11. 10
      src/google/protobuf/editions/golden/editions_transform_proto3_utf8_disabled.proto
  12. 2
      src/google/protobuf/editions/golden/test_messages_proto2.proto
  13. 2
      src/google/protobuf/editions/golden/test_messages_proto3.proto
  14. 20
      src/google/protobuf/editions/transform.awk

@ -78,17 +78,6 @@ absl::flat_hash_map<absl::string_view, std::string> CommonVars(
}; };
} }
static bool IsStringMapType(const FieldDescriptor& field) {
if (!field.is_map()) return false;
for (int i = 0; i < field.message_type()->field_count(); ++i) {
if (field.message_type()->field(i)->type() ==
FieldDescriptor::TYPE_STRING) {
return true;
}
}
return false;
}
} // namespace } // namespace
bool CppGenerator::Generate(const FileDescriptor* file, bool CppGenerator::Generate(const FileDescriptor* file,
@ -352,14 +341,6 @@ absl::Status CppGenerator::ValidateFeatures(const FileDescriptor* file) const {
absl::StrCat("Field ", field.full_name(), absl::StrCat("Field ", field.full_name(),
" has a closed enum type with implicit presence.")); " has a closed enum type with implicit presence."));
} }
if (resolved_features.GetExtension(::pb::cpp).utf8_validation() ==
pb::CppFeatures::UTF8_VALIDATION_UNKNOWN) {
status = absl::FailedPreconditionError(absl::StrCat(
"Field ", field.full_name(),
" has an unknown value for the utf8_validation feature. ",
resolved_features.DebugString(),
"\nRawFeatures: ", unresolved_features));
}
if (field.containing_type() == nullptr || if (field.containing_type() == nullptr ||
!field.containing_type()->options().map_entry()) { !field.containing_type()->options().map_entry()) {
@ -374,14 +355,6 @@ absl::Status CppGenerator::ValidateFeatures(const FileDescriptor* file) const {
" specifies the legacy_closed_enum feature but has " " specifies the legacy_closed_enum feature but has "
"non-enum type.")); "non-enum type."));
} }
if (field.type() != FieldDescriptor::TYPE_STRING &&
!IsStringMapType(field) &&
unresolved_features.has_utf8_validation()) {
status = absl::FailedPreconditionError(
absl::StrCat("Field ", field.full_name(),
" specifies the utf8_validation feature but is not of "
"string type."));
}
} }
#ifdef PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE #ifdef PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE

@ -148,88 +148,6 @@ TEST_F(CppGeneratorTest, LegacyClosedEnumImplicit) {
"Field Foo.bar has a closed enum type with implicit presence."); "Field Foo.bar has a closed enum type with implicit presence.");
} }
TEST_F(CppGeneratorTest, Utf8ValidationMap) {
CreateTempFile("foo.proto", R"schema(
edition = "2023";
import "google/protobuf/cpp_features.proto";
message Foo {
map<string, string> map_field = 1 [
features.(pb.cpp).utf8_validation = NONE
];
map<int32, string> map_field_value = 2 [
features.(pb.cpp).utf8_validation = VERIFY_PARSE
];
map<string, int32> map_field_key = 3 [
features.(pb.cpp).utf8_validation = VERIFY_DLOG
];
}
)schema");
RunProtoc(
"protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir "
"--experimental_editions foo.proto");
ExpectNoErrors();
}
TEST_F(CppGeneratorTest, Utf8ValidationNonString) {
CreateTempFile("foo.proto", R"schema(
edition = "2023";
import "google/protobuf/cpp_features.proto";
message Foo {
int64 bar = 1 [
features.(pb.cpp).utf8_validation = NONE
];
}
)schema");
RunProtoc(
"protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir "
"--experimental_editions foo.proto");
ExpectErrorSubstring("Field Foo.bar specifies the utf8_validation feature");
}
TEST_F(CppGeneratorTest, Utf8ValidationNonStringMap) {
CreateTempFile("foo.proto", R"schema(
edition = "2023";
import "google/protobuf/cpp_features.proto";
message Foo {
map<int64, int64> bar = 1 [
features.(pb.cpp).utf8_validation = VERIFY_PARSE
];
}
)schema");
RunProtoc(
"protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir "
"--experimental_editions foo.proto");
ExpectErrorSubstring("Field Foo.bar specifies the utf8_validation feature");
}
TEST_F(CppGeneratorTest, Utf8ValidationUnknownValue) {
CreateTempFile("foo.proto", R"schema(
edition = "2023";
import "google/protobuf/cpp_features.proto";
message Foo {
string bar = 1 [
features.(pb.cpp).utf8_validation = UTF8_VALIDATION_UNKNOWN
];
}
)schema");
RunProtoc(
"protocol_compiler --proto_path=$tmpdir --cpp_out=$tmpdir "
"--experimental_editions foo.proto");
ExpectErrorSubstring(
"Field Foo.bar has an unknown value for the utf8_validation feature.");
}
#ifdef PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE #ifdef PROTOBUF_FUTURE_REMOVE_WRONG_CTYPE
TEST_F(CppGeneratorTest, CtypeOnNoneStringFieldTest) { TEST_F(CppGeneratorTest, CtypeOnNoneStringFieldTest) {
CreateTempFile("foo.proto", CreateTempFile("foo.proto",

@ -1110,9 +1110,8 @@ FeatureSet* CreateProto2DefaultFeatures() {
features->set_repeated_field_encoding(FeatureSet::EXPANDED); features->set_repeated_field_encoding(FeatureSet::EXPANDED);
features->set_message_encoding(FeatureSet::LENGTH_PREFIXED); features->set_message_encoding(FeatureSet::LENGTH_PREFIXED);
features->set_json_format(FeatureSet::LEGACY_BEST_EFFORT); features->set_json_format(FeatureSet::LEGACY_BEST_EFFORT);
features->set_utf8_validation(FeatureSet::NONE);
features->MutableExtension(pb::cpp)->set_legacy_closed_enum(true); features->MutableExtension(pb::cpp)->set_legacy_closed_enum(true);
features->MutableExtension(pb::cpp)->set_utf8_validation(
pb::CppFeatures::VERIFY_DLOG);
return features; return features;
} }
@ -1137,11 +1136,10 @@ const FeatureSet& GetProto3Features() {
features->set_field_presence(FeatureSet::IMPLICIT); features->set_field_presence(FeatureSet::IMPLICIT);
features->set_enum_type(FeatureSet::OPEN); features->set_enum_type(FeatureSet::OPEN);
features->set_repeated_field_encoding(FeatureSet::PACKED); features->set_repeated_field_encoding(FeatureSet::PACKED);
features->set_utf8_validation(FeatureSet::VERIFY);
features->set_message_encoding(FeatureSet::LENGTH_PREFIXED); features->set_message_encoding(FeatureSet::LENGTH_PREFIXED);
features->set_json_format(FeatureSet::ALLOW); features->set_json_format(FeatureSet::ALLOW);
features->MutableExtension(pb::cpp)->set_legacy_closed_enum(false); features->MutableExtension(pb::cpp)->set_legacy_closed_enum(false);
features->MutableExtension(pb::cpp)->set_utf8_validation(
pb::CppFeatures::VERIFY_PARSE);
return features; return features;
}(); }();
return *kProto3Features; return *kProto3Features;
@ -3805,8 +3803,7 @@ bool FieldDescriptor::is_packed() const {
static bool IsStrictUtf8(const FieldDescriptor* field) { static bool IsStrictUtf8(const FieldDescriptor* field) {
return internal::InternalFeatureHelper::GetFeatures(*field) return internal::InternalFeatureHelper::GetFeatures(*field)
.GetExtension(pb::cpp) .utf8_validation() == FeatureSet::VERIFY;
.utf8_validation() == pb::CppFeatures::VERIFY_PARSE;
} }
bool FieldDescriptor::requires_utf8_validation() const { bool FieldDescriptor::requires_utf8_validation() const {
@ -7901,6 +7898,17 @@ void DescriptorBuilder::ValidateOptions(const FieldDescriptor* field,
} }
} }
static bool IsStringMapType(const FieldDescriptor& field) {
if (!field.is_map()) return false;
for (int i = 0; i < field.message_type()->field_count(); ++i) {
if (field.message_type()->field(i)->type() ==
FieldDescriptor::TYPE_STRING) {
return true;
}
}
return false;
}
void DescriptorBuilder::ValidateFieldFeatures( void DescriptorBuilder::ValidateFieldFeatures(
const FieldDescriptor* field, const FieldDescriptorProto& proto) { const FieldDescriptor* field, const FieldDescriptorProto& proto) {
// Rely on our legacy validation for proto2/proto3 files. // Rely on our legacy validation for proto2/proto3 files.
@ -7967,6 +7975,12 @@ void DescriptorBuilder::ValidateFieldFeatures(
AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
"Only repeated fields can specify repeated field encoding."); "Only repeated fields can specify repeated field encoding.");
} }
if (field->type() != FieldDescriptor::TYPE_STRING &&
!IsStringMapType(*field) &&
field->proto_features_->has_utf8_validation()) {
AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
"Only string fields can specify utf8 validation.");
}
if (!field->is_packable() && if (!field->is_packable() &&
field->proto_features_->repeated_field_encoding() == FeatureSet::PACKED) { field->proto_features_->repeated_field_encoding() == FeatureSet::PACKED) {
AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME, AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,

@ -7316,32 +7316,26 @@ TEST_F(FeaturesTest, Proto2Features) {
field_presence: EXPLICIT field_presence: EXPLICIT
enum_type: CLOSED enum_type: CLOSED
repeated_field_encoding: EXPANDED repeated_field_encoding: EXPANDED
utf8_validation: NONE
message_encoding: LENGTH_PREFIXED message_encoding: LENGTH_PREFIXED
json_format: LEGACY_BEST_EFFORT json_format: LEGACY_BEST_EFFORT
[pb.cpp] { [pb.cpp] { legacy_closed_enum: true })pb"));
legacy_closed_enum: true
utf8_validation: VERIFY_DLOG
})pb"));
EXPECT_THAT(GetFeatures(field), EqualsProto(R"pb( EXPECT_THAT(GetFeatures(field), EqualsProto(R"pb(
field_presence: EXPLICIT field_presence: EXPLICIT
enum_type: CLOSED enum_type: CLOSED
repeated_field_encoding: EXPANDED repeated_field_encoding: EXPANDED
utf8_validation: NONE
message_encoding: LENGTH_PREFIXED message_encoding: LENGTH_PREFIXED
json_format: LEGACY_BEST_EFFORT json_format: LEGACY_BEST_EFFORT
[pb.cpp] { [pb.cpp] { legacy_closed_enum: true })pb"));
legacy_closed_enum: true
utf8_validation: VERIFY_DLOG
})pb"));
EXPECT_THAT(GetFeatures(group), EqualsProto(R"pb( EXPECT_THAT(GetFeatures(group), EqualsProto(R"pb(
field_presence: EXPLICIT field_presence: EXPLICIT
enum_type: CLOSED enum_type: CLOSED
repeated_field_encoding: EXPANDED repeated_field_encoding: EXPANDED
utf8_validation: NONE
message_encoding: DELIMITED message_encoding: DELIMITED
json_format: LEGACY_BEST_EFFORT json_format: LEGACY_BEST_EFFORT
[pb.cpp] { [pb.cpp] { legacy_closed_enum: true })pb"));
legacy_closed_enum: true
utf8_validation: VERIFY_DLOG
})pb"));
EXPECT_TRUE(field->has_presence()); EXPECT_TRUE(field->has_presence());
EXPECT_FALSE(field->requires_utf8_validation()); EXPECT_FALSE(field->requires_utf8_validation());
EXPECT_EQ(GetUtf8CheckMode(field, /*is_lite=*/false), Utf8CheckMode::kVerify); EXPECT_EQ(GetUtf8CheckMode(field, /*is_lite=*/false), Utf8CheckMode::kVerify);
@ -7395,22 +7389,18 @@ TEST_F(FeaturesTest, Proto3Features) {
field_presence: IMPLICIT field_presence: IMPLICIT
enum_type: OPEN enum_type: OPEN
repeated_field_encoding: PACKED repeated_field_encoding: PACKED
utf8_validation: VERIFY
message_encoding: LENGTH_PREFIXED message_encoding: LENGTH_PREFIXED
json_format: ALLOW json_format: ALLOW
[pb.cpp] { [pb.cpp] { legacy_closed_enum: false })pb"));
legacy_closed_enum: false
utf8_validation: VERIFY_PARSE
})pb"));
EXPECT_THAT(GetFeatures(field), EqualsProto(R"pb( EXPECT_THAT(GetFeatures(field), EqualsProto(R"pb(
field_presence: IMPLICIT field_presence: IMPLICIT
enum_type: OPEN enum_type: OPEN
repeated_field_encoding: PACKED repeated_field_encoding: PACKED
utf8_validation: VERIFY
message_encoding: LENGTH_PREFIXED message_encoding: LENGTH_PREFIXED
json_format: ALLOW json_format: ALLOW
[pb.cpp] { [pb.cpp] { legacy_closed_enum: false })pb"));
legacy_closed_enum: false
utf8_validation: VERIFY_PARSE
})pb"));
EXPECT_FALSE(field->has_presence()); EXPECT_FALSE(field->has_presence());
EXPECT_FALSE(field->requires_utf8_validation()); EXPECT_FALSE(field->requires_utf8_validation());
EXPECT_EQ(GetUtf8CheckMode(field, /*is_lite=*/false), Utf8CheckMode::kStrict); EXPECT_EQ(GetUtf8CheckMode(field, /*is_lite=*/false), Utf8CheckMode::kStrict);
@ -8316,6 +8306,52 @@ TEST_F(FeaturesTest, MapFieldFeaturesOverride) {
validate(value); validate(value);
} }
TEST_F(FeaturesTest, MapFieldFeaturesStringValidation) {
constexpr absl::string_view kProtoFile = R"schema(
edition = "2023";
message Foo {
map<string, string> map_field = 1 [
features.utf8_validation = NONE
];
map<int32, string> map_field_value = 2 [
features.utf8_validation = NONE
];
map<string, int32> map_field_key = 3 [
features.utf8_validation = NONE
];
}
)schema";
io::ArrayInputStream input_stream(kProtoFile.data(), kProtoFile.size());
SimpleErrorCollector error_collector;
io::Tokenizer tokenizer(&input_stream, &error_collector);
compiler::Parser parser;
parser.RecordErrorsTo(&error_collector);
FileDescriptorProto proto;
ASSERT_TRUE(parser.Parse(&tokenizer, &proto))
<< error_collector.last_error() << "\n"
<< kProtoFile;
ASSERT_EQ("", error_collector.last_error());
proto.set_name("foo.proto");
BuildDescriptorMessagesInTestPool();
const FileDescriptor* file = pool_.BuildFile(proto);
ASSERT_THAT(file, NotNull());
auto validate_map_field = [](const FieldDescriptor* field) {
const FieldDescriptor* key = field->message_type()->field(0);
const FieldDescriptor* value = field->message_type()->field(1);
EXPECT_FALSE(field->requires_utf8_validation()) << field->DebugString();
EXPECT_FALSE(key->requires_utf8_validation()) << field->DebugString();
EXPECT_FALSE(value->requires_utf8_validation()) << field->DebugString();
};
validate_map_field(file->message_type(0)->field(0));
validate_map_field(file->message_type(0)->field(1));
validate_map_field(file->message_type(0)->field(2));
}
TEST_F(FeaturesTest, RootExtensionFeaturesOverride) { TEST_F(FeaturesTest, RootExtensionFeaturesOverride) {
BuildDescriptorMessagesInTestPool(); BuildDescriptorMessagesInTestPool();
BuildFileInTestPool(pb::TestFeatures::descriptor()->file()); BuildFileInTestPool(pb::TestFeatures::descriptor()->file());
@ -8967,11 +9003,9 @@ TEST_F(FeaturesTest, MethodFeaturesOverride) {
TEST_F(FeaturesTest, FieldFeatureHelpers) { TEST_F(FeaturesTest, FieldFeatureHelpers) {
BuildDescriptorMessagesInTestPool(); BuildDescriptorMessagesInTestPool();
BuildFileInTestPool(pb::CppFeatures::GetDescriptor()->file());
const FileDescriptor* file = BuildFile(R"pb( const FileDescriptor* file = BuildFile(R"pb(
name: "foo.proto" name: "foo.proto"
syntax: "editions" syntax: "editions"
dependency: "google/protobuf/cpp_features.proto"
edition: EDITION_2023 edition: EDITION_2023
message_type { message_type {
name: "Foo" name: "Foo"
@ -9011,22 +9045,7 @@ TEST_F(FeaturesTest, FieldFeatureHelpers) {
number: 7 number: 7
label: LABEL_REPEATED label: LABEL_REPEATED
type: TYPE_STRING type: TYPE_STRING
options { options { features { utf8_validation: NONE } }
features {
[pb.cpp] { utf8_validation: VERIFY_DLOG }
}
}
}
field {
name: "utf8_none_field"
number: 8
label: LABEL_REPEATED
type: TYPE_STRING
options {
features {
[pb.cpp] { utf8_validation: NONE }
}
}
} }
} }
)pb"); )pb");
@ -9038,7 +9057,6 @@ TEST_F(FeaturesTest, FieldFeatureHelpers) {
const FieldDescriptor* required_message_field = message->field(4); const FieldDescriptor* required_message_field = message->field(4);
const FieldDescriptor* expanded_field = message->field(5); const FieldDescriptor* expanded_field = message->field(5);
const FieldDescriptor* utf8_verify_field = message->field(6); const FieldDescriptor* utf8_verify_field = message->field(6);
const FieldDescriptor* utf8_none_field = message->field(7);
EXPECT_FALSE(default_field->is_packed()); EXPECT_FALSE(default_field->is_packed());
EXPECT_FALSE(default_field->is_required()); EXPECT_FALSE(default_field->is_required());
@ -9069,7 +9087,6 @@ TEST_F(FeaturesTest, FieldFeatureHelpers) {
Utf8CheckMode::kVerify); Utf8CheckMode::kVerify);
EXPECT_EQ(GetUtf8CheckMode(utf8_verify_field, /*is_lite=*/true), EXPECT_EQ(GetUtf8CheckMode(utf8_verify_field, /*is_lite=*/true),
Utf8CheckMode::kNone); Utf8CheckMode::kNone);
EXPECT_FALSE(utf8_none_field->requires_utf8_validation());
EXPECT_EQ(GetUtf8CheckMode(utf8_verify_field, /*is_lite=*/false), EXPECT_EQ(GetUtf8CheckMode(utf8_verify_field, /*is_lite=*/false),
Utf8CheckMode::kVerify); Utf8CheckMode::kVerify);
EXPECT_EQ(GetUtf8CheckMode(utf8_verify_field, /*is_lite=*/true), EXPECT_EQ(GetUtf8CheckMode(utf8_verify_field, /*is_lite=*/true),
@ -9432,6 +9449,86 @@ TEST_F(FeaturesTest, InvalidFieldOneofRequired) {
"foo.proto: Foo.bar: NAME: Oneof fields can't specify field presence.\n"); "foo.proto: Foo.bar: NAME: Oneof fields can't specify field presence.\n");
} }
TEST_F(FeaturesTest, InvalidFieldNonStringWithStringValidation) {
BuildDescriptorMessagesInTestPool();
BuildFileWithErrors(
R"pb(
name: "foo.proto"
syntax: "editions"
edition: EDITION_2023
message_type {
name: "Foo"
field {
name: "bar"
number: 1
label: LABEL_OPTIONAL
type: TYPE_INT64
options { features { utf8_validation: NONE } }
}
}
)pb",
"foo.proto: Foo.bar: NAME: Only string fields can specify "
"utf8 validation.\n");
}
TEST_F(FeaturesTest, InvalidFieldNonStringMapWithStringValidation) {
BuildDescriptorMessagesInTestPool();
BuildFileWithErrors(
R"pb(
name: "foo.proto"
syntax: "editions"
edition: EDITION_2023
message_type {
name: "Foo"
nested_type {
name: "MapFieldEntry"
field {
name: "key"
number: 1
label: LABEL_OPTIONAL
type: TYPE_INT32
options {
uninterpreted_option {
name { name_part: "features" is_extension: false }
name { name_part: "utf8_validation" is_extension: false }
identifier_value: "NONE"
}
}
}
field {
name: "value"
number: 2
label: LABEL_OPTIONAL
type: TYPE_INT32
options {
uninterpreted_option {
name { name_part: "features" is_extension: false }
name { name_part: "utf8_validation" is_extension: false }
identifier_value: "NONE"
}
}
}
options { map_entry: true }
}
field {
name: "map_field"
number: 1
label: LABEL_REPEATED
type_name: "MapFieldEntry"
options {
uninterpreted_option {
name { name_part: "features" is_extension: false }
name { name_part: "utf8_validation" is_extension: false }
identifier_value: "NONE"
}
}
}
}
)pb",
"foo.proto: Foo.map_field: NAME: Only string fields can specify "
"utf8 validation.\n");
}
TEST_F(FeaturesTest, InvalidFieldNonRepeatedWithRepeatedEncoding) { TEST_F(FeaturesTest, InvalidFieldNonRepeatedWithRepeatedEncoding) {
BuildDescriptorMessagesInTestPool(); BuildDescriptorMessagesInTestPool();
BuildFileWithErrors( BuildFileWithErrors(

@ -35,14 +35,6 @@
total_size += ::_pbi::WireFormatLite::Int32SizePlusOne( total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(
[ FAILED ] third_party/protobuf/editions/golden/simple_proto3.pb.cc [ FAILED ] third_party/protobuf/editions/golden/simple_proto3.pb.cc
[ RUN ] third_party/protobuf/editions/golden/simple_proto3.pb.h [ RUN ] third_party/protobuf/editions/golden/simple_proto3.pb.h
@@ @@
#include "third_party/protobuf/generated_message_util.h"
#include "third_party/protobuf/metadata_lite.h"
#include "third_party/protobuf/message_lite.h"
+#include "third_party/protobuf/cpp_features.pb.h"
// @@protoc_insertion_point(includes)
// Must be included last.
@@ @@ @@ @@
enum : int { enum : int {
kInt32FieldFieldNumber = 1, kInt32FieldFieldNumber = 1,

@ -5,7 +5,7 @@
<failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.cc&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;&#x0A;#include &quot;third_party/protobuf/editions/golden/simple_proto3.pb.h&quot;&#x0A;&#x0A;#include &lt;algorithm&gt;&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/extension_set.h&quot;&#x0A;#include &quot;third_party/protobuf/wire_format_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/io/zero_copy_stream_impl_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_impl.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;, with the difference:&#x0A;@@ @@&#x0A; &amp;_SimpleProto3_default_instance_._instance,&#x0A; ::_pbi::TcParser::GenericFallbackLite, // fallback&#x0A; }, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; {::_pbi::TcParser::FastV32S1,&#x0A; {8, 0, 0, PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_)}},&#x0A; }}, {{&#x0A; 65535, 65535&#x0A; }}, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; {PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_), _Internal::kHasBitsOffset + 0, 0,&#x0A; (0 | ::_fl::kFcOptional | ::_fl::kInt32)},&#x0A; }},&#x0A;@@ @@&#x0A; (void)cached_has_bits;&#x0A; &#x0A; cached_has_bits = _impl_._has_bits_[0];&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; if (cached_has_bits &amp; 0x00000001u) {&#x0A; target = ::proto2::internal::WireFormatLite::&#x0A; WriteInt32ToArrayWithField&lt;1&gt;(&#x0A;@@ @@&#x0A; // Prevent compiler warnings about cached_has_bits being unused&#x0A; (void) cached_has_bits;&#x0A; &#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; cached_has_bits = _impl_._has_bits_[0];&#x0A; if (cached_has_bits &amp; 0x00000001u) {&#x0A; total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(" type=""></failure> <failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.cc&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;&#x0A;#include &quot;third_party/protobuf/editions/golden/simple_proto3.pb.h&quot;&#x0A;&#x0A;#include &lt;algorithm&gt;&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/extension_set.h&quot;&#x0A;#include &quot;third_party/protobuf/wire_format_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/io/zero_copy_stream_impl_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_impl.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;, with the difference:&#x0A;@@ @@&#x0A; &amp;_SimpleProto3_default_instance_._instance,&#x0A; ::_pbi::TcParser::GenericFallbackLite, // fallback&#x0A; }, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; {::_pbi::TcParser::FastV32S1,&#x0A; {8, 0, 0, PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_)}},&#x0A; }}, {{&#x0A; 65535, 65535&#x0A; }}, {{&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; {PROTOBUF_FIELD_OFFSET(SimpleProto3, _impl_.int32_field_), _Internal::kHasBitsOffset + 0, 0,&#x0A; (0 | ::_fl::kFcOptional | ::_fl::kInt32)},&#x0A; }},&#x0A;@@ @@&#x0A; (void)cached_has_bits;&#x0A; &#x0A; cached_has_bits = _impl_._has_bits_[0];&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; if (cached_has_bits &amp; 0x00000001u) {&#x0A; target = ::proto2::internal::WireFormatLite::&#x0A; WriteInt32ToArrayWithField&lt;1&gt;(&#x0A;@@ @@&#x0A; // Prevent compiler warnings about cached_has_bits being unused&#x0A; (void) cached_has_bits;&#x0A; &#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; cached_has_bits = _impl_._has_bits_[0];&#x0A; if (cached_has_bits &amp; 0x00000001u) {&#x0A; total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(" type=""></failure>
</testcase> </testcase>
<testcase name="third_party/protobuf/editions/golden/simple_proto3.pb.h" status="run" result="completed" classname="DiffTest"> <testcase name="third_party/protobuf/editions/golden/simple_proto3.pb.h" status="run" result="completed" classname="DiffTest">
<failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.h&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;&#x0A;#ifndef GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;#define GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;&#x0A;#include &lt;limits&gt;&#x0A;#include &lt;string&gt;&#x0A;#include &lt;type_traits&gt;&#x0A;#include &lt;utility&gt;&#x0A;&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/arena.h&quot;&#x0A;#include &quot;third_party/protobuf/arenastring.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_decl.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_util.h&quot;&#x0A;#include &quot;third_party/protobuf/metadata_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/message_lite.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;&#x0A;#endif // GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;, with the difference:&#x0A;@@ @@&#x0A; #include &quot;third_party/protobuf/generated_message_util.h&quot;&#x0A; #include &quot;third_party/protobuf/metadata_lite.h&quot;&#x0A; #include &quot;third_party/protobuf/message_lite.h&quot;&#x0A;+#include &quot;third_party/protobuf/cpp_features.pb.h&quot;&#x0A; // @@protoc_insertion_point(includes)&#x0A; &#x0A; // Must be included last.&#x0A;@@ @@&#x0A; enum : int {&#x0A; kInt32FieldFieldNumber = 1,&#x0A; };&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; bool has_int32_field() const;&#x0A; void clear_int32_field() ;&#x0A; ::int32_t int32_field() const;&#x0A;@@ @@&#x0A; &#x0A; // SimpleProto3&#x0A; &#x0A;-// optional int32 int32_field = 1;&#x0A;+// int32 int32_field = 1 [features = {&#x0A; inline bool SimpleProto3::has_int32_field() const {&#x0A; bool value = (_impl_._has_bits_[0] &amp; 0x00000001u) != 0;&#x0A; return value;" type=""></failure> <failure message="Value of: third_party/protobuf/editions/golden/simple_proto3.pb.h&#x0A;Expected: &#x0A;// Generated by the protocol buffer compiler. DO NOT EDIT!&#x0A;// source: third_party/protobuf/editions/golden/simple_proto3.proto&#x0A;&#x0A;#ifndef GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;#define GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;&#x0A;#include &lt;limits&gt;&#x0A;#include &lt;string&gt;&#x0A;#include &lt;type_traits&gt;&#x0A;#include &lt;utility&gt;&#x0A;&#x0A;#include &quot;third_party/protobuf/io/coded_stream.h&quot;&#x0A;#include &quot;third_party/protobuf/arena.h&quot;&#x0A;#include &quot;third_party/protobuf/arenastring.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_tctable_decl.h&quot;&#x0A;#include &quot;third_party/protobuf/generated_message_util.h&quot;&#x0A;#include &quot;third_party/protobuf/metadata_lite.h&quot;&#x0A;#include &quot;third_party/protobuf/message_lite.h&quot;&#x0A;// @@protoc_insertion_point(includes)&#x0A;&#x0A;// Must be included last.&#x0A;&#x0A;#endif // GOOGLE_PROTOBUF_INCLUDED_third_5fparty_2fprotobuf_2feditions_2fgolden_2fsimple_5fproto3_2eproto_2epb_2eh&#x0A;, with the difference:&#x0A;@@ @@&#x0A; enum : int {&#x0A; kInt32FieldFieldNumber = 1,&#x0A; };&#x0A;- // optional int32 int32_field = 1;&#x0A;+ // int32 int32_field = 1 [features = {&#x0A; bool has_int32_field() const;&#x0A; void clear_int32_field() ;&#x0A; ::int32_t int32_field() const;&#x0A;@@ @@&#x0A; &#x0A; // SimpleProto3&#x0A; &#x0A;-// optional int32 int32_field = 1;&#x0A;+// int32 int32_field = 1 [features = {&#x0A; inline bool SimpleProto3::has_int32_field() const {&#x0A; bool value = (_impl_._has_bits_[0] &amp; 0x00000001u) != 0;&#x0A; return value;" type=""></failure>
</testcase> </testcase>
<testcase name="third_party/protobuf/editions/golden/simple_proto3.proto.static_reflection.h" status="run" result="completed" classname="DiffTest"> <testcase name="third_party/protobuf/editions/golden/simple_proto3.proto.static_reflection.h" status="run" result="completed" classname="DiffTest">
</testcase> </testcase>

@ -9,9 +9,9 @@ edition = "2023";
import "google/protobuf/cpp_features.proto"; import "google/protobuf/cpp_features.proto";
option features.enum_type = CLOSED; option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED; option features.repeated_field_encoding = EXPANDED;
option features.utf8_validation = NONE;
option features.json_format = LEGACY_BEST_EFFORT; option features.json_format = LEGACY_BEST_EFFORT;
option features.(pb.cpp).legacy_closed_enum = true; option features.(pb.cpp).legacy_closed_enum = true;
option features.(pb.cpp).utf8_validation = VERIFY_DLOG;
// This file contains various edge cases we've collected from migrating real // This file contains various edge cases we've collected from migrating real
// protos in order to lock down the transformations. // protos in order to lock down the transformations.

@ -9,9 +9,9 @@ edition = "2023";
import "google/protobuf/cpp_features.proto"; import "google/protobuf/cpp_features.proto";
option features.enum_type = CLOSED; option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED; option features.repeated_field_encoding = EXPANDED;
option features.utf8_validation = NONE;
option features.json_format = LEGACY_BEST_EFFORT; option features.json_format = LEGACY_BEST_EFFORT;
option features.(pb.cpp).legacy_closed_enum = true; option features.(pb.cpp).legacy_closed_enum = true;
option features.(pb.cpp).utf8_validation = VERIFY_DLOG;
package protobuf_editions_test; package protobuf_editions_test;

@ -9,19 +9,19 @@ edition = "2023";
import "google/protobuf/cpp_features.proto"; import "google/protobuf/cpp_features.proto";
option features.enum_type = CLOSED; option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED; option features.repeated_field_encoding = EXPANDED;
option features.utf8_validation = NONE;
option features.json_format = LEGACY_BEST_EFFORT; option features.json_format = LEGACY_BEST_EFFORT;
option features.(pb.cpp).legacy_closed_enum = true; option features.(pb.cpp).legacy_closed_enum = true;
option features.(pb.cpp).utf8_validation = VERIFY_DLOG;
package protobuf_editions_test; package protobuf_editions_test;
message TestMessageUtf8Disabled { message TestMessageUtf8Disabled {
string string_field = 1 [features.(pb.cpp).utf8_validation = NONE]; string string_field = 1;
string string_field_utf = 2 [features.(pb.cpp).utf8_validation = NONE]; string string_field_utf = 2;
string string_field_noutf = 3 [features.(pb.cpp).utf8_validation = NONE]; string string_field_noutf = 3;
map<string, string> string_map_field = 4 [features.(pb.cpp).utf8_validation = NONE]; map<string, string> string_map_field = 4;
int32 int_field = 5; int32 int_field = 5;
} }

@ -6,20 +6,18 @@
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
edition = "2023"; edition = "2023";
import "google/protobuf/cpp_features.proto";
option features.field_presence = IMPLICIT; option features.field_presence = IMPLICIT;
option features.(pb.cpp).utf8_validation = VERIFY_PARSE;
package protobuf_editions_test; package protobuf_editions_test;
message TestMessageProto3 { message TestMessageProto3 {
string string_field = 1; string string_field = 1;
string string_field_utf = 2; string string_field_utf = 2;
string string_field_noutf = 3 [features.(pb.cpp).utf8_validation = VERIFY_DLOG]; string string_field_noutf = 3 [features.utf8_validation = NONE];
map<string, string> string_map_field = 4; map<string, string> string_map_field = 4;
map<string, string> string_map_field_utf = 5; map<string, string> string_map_field_utf = 5;
map<string, string> string_map_field_noutf = 6 [features.(pb.cpp).utf8_validation = VERIFY_DLOG]; map<string, string> string_map_field_noutf = 6 [features.utf8_validation = NONE];
repeated int32 int_field = 7; repeated int32 int_field = 7;
repeated int32 int_field_packed = 8; repeated int32 int_field_packed = 8;

@ -6,19 +6,17 @@
// https://developers.google.com/open-source/licenses/bsd // https://developers.google.com/open-source/licenses/bsd
edition = "2023"; edition = "2023";
import "google/protobuf/cpp_features.proto";
option features.field_presence = IMPLICIT; option features.field_presence = IMPLICIT;
option features.(pb.cpp).utf8_validation = VERIFY_PARSE;
package protobuf_editions_test; package protobuf_editions_test;
message TestMessageProto3 { message TestMessageProto3 {
string string_field = 1 [features.(pb.cpp).utf8_validation = NONE]; string string_field = 1;
string string_field_utf = 2 [features.(pb.cpp).utf8_validation = NONE]; string string_field_utf = 2;
string string_field_noutf = 3 [features.(pb.cpp).utf8_validation = NONE]; string string_field_noutf = 3 [features.utf8_validation = NONE];
map<string, string> string_map_field = 4 [features.(pb.cpp).utf8_validation = NONE]; map<string, string> string_map_field = 4;
repeated int32 int_field = 7; repeated int32 int_field = 7;
} }

@ -16,9 +16,9 @@ edition = "2023";
import "google/protobuf/cpp_features.proto"; import "google/protobuf/cpp_features.proto";
option features.enum_type = CLOSED; option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED; option features.repeated_field_encoding = EXPANDED;
option features.utf8_validation = NONE;
option features.json_format = LEGACY_BEST_EFFORT; option features.json_format = LEGACY_BEST_EFFORT;
option features.(pb.cpp).legacy_closed_enum = true; option features.(pb.cpp).legacy_closed_enum = true;
option features.(pb.cpp).utf8_validation = VERIFY_DLOG;
package protobuf_test_messages.proto2; package protobuf_test_messages.proto2;

@ -13,9 +13,7 @@
// //
edition = "2023"; edition = "2023";
import "google/protobuf/cpp_features.proto";
option features.field_presence = IMPLICIT; option features.field_presence = IMPLICIT;
option features.(pb.cpp).utf8_validation = VERIFY_PARSE;
package protobuf_test_messages.proto3; package protobuf_test_messages.proto3;

@ -77,17 +77,10 @@ function transform_field(field)
sub(/\<required\s*/, "", field_def) sub(/\<required\s*/, "", field_def)
options[++num_options] = "features.field_presence = LEGACY_REQUIRED" options[++num_options] = "features.field_presence = LEGACY_REQUIRED"
} }
if (disable_utf8 && match(field_def, /^\s*(string|repeated\s*string|map<string,\s*string>)/)) {
options[++num_options] = "features.(pb.cpp).utf8_validation = NONE"
}
} }
if(syntax == 3) { if(syntax == 3) {
if (disable_utf8 && match(field_def, /^\s*(string|repeated\s*string|map<string,\s*string>)/)) { sub(/\<enforce_utf8 = false\>/, "features.utf8_validation = NONE", existing_options)
options[++num_options] = "features.(pb.cpp).utf8_validation = NONE"
} else {
sub(/\<enforce_utf8 = false\>/, "features.(pb.cpp).utf8_validation = VERIFY_DLOG", existing_options)
}
sub(/\<packed = false\>/, "features.repeated_field_encoding = EXPANDED", existing_options) sub(/\<packed = false\>/, "features.repeated_field_encoding = EXPANDED", existing_options)
existing_options = strip_option("packed = true", existing_options) existing_options = strip_option("packed = true", existing_options)
existing_options = strip_option("enforce_utf8 = (true|false)", existing_options) existing_options = strip_option("enforce_utf8 = (true|false)", existing_options)
@ -121,29 +114,20 @@ function transform_field(field)
print "import \"third_party/protobuf/cpp_features.proto\";" print "import \"third_party/protobuf/cpp_features.proto\";"
print "option features.enum_type = CLOSED;" print "option features.enum_type = CLOSED;"
print "option features.repeated_field_encoding = EXPANDED;" print "option features.repeated_field_encoding = EXPANDED;"
print "option features.utf8_validation = NONE;"
print "option features.json_format = LEGACY_BEST_EFFORT;" print "option features.json_format = LEGACY_BEST_EFFORT;"
print "option features.(pb.cpp).legacy_closed_enum = true;" print "option features.(pb.cpp).legacy_closed_enum = true;"
print "option features.(pb.cpp).utf8_validation = VERIFY_DLOG;"
syntax = 2 syntax = 2
next next
} }
/syntax = "proto3"/ { /syntax = "proto3"/ {
print "edition = \"2023\";" print "edition = \"2023\";"
print "import \"third_party/protobuf/cpp_features.proto\";"
print "option features.field_presence = IMPLICIT;" print "option features.field_presence = IMPLICIT;"
print "option features.(pb.cpp).utf8_validation = VERIFY_PARSE;"
syntax = 3 syntax = 3
next next
} }
# utf8 validation handling
/option (cc_utf8_verification\s*=\s*false)/ {
disable_utf8 = 1
# Strip this option and replace with feature setting.
next;
}
# Group handling. # Group handling.
/\<group \w* = [0-9]* {/, /}/ { /\<group \w* = [0-9]* {/, /}/ {
if (match($0, /\<group\>/)) { if (match($0, /\<group\>/)) {

Loading…
Cancel
Save