aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/google/protobuf/compiler/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/google/protobuf/compiler/cpp')
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.cc88
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_helpers.h19
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_map_field.cc63
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_string_field.cc84
4 files changed, 197 insertions, 57 deletions
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.cc b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
index 678a995a..09845458 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.cc
@@ -600,6 +600,94 @@ bool IsAnyMessage(const Descriptor* descriptor) {
descriptor->file()->name() == kAnyProtoFile;
}
+enum Utf8CheckMode {
+ STRICT = 0, // Parsing will fail if non UTF-8 data is in string fields.
+ VERIFY = 1, // Only log an error but parsing will succeed.
+ NONE = 2, // No UTF-8 check.
+};
+
+// Which level of UTF-8 enforcemant is placed on this file.
+static Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field) {
+ if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
+ return STRICT;
+ } else if (field->file()->options().optimize_for() !=
+ FileOptions::LITE_RUNTIME) {
+ return VERIFY;
+ } else {
+ return NONE;
+ }
+}
+
+static void GenerateUtf8CheckCode(const FieldDescriptor* field,
+ bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ const char* strict_function,
+ const char* verify_function,
+ io::Printer* printer) {
+ switch (GetUtf8CheckMode(field)) {
+ case STRICT: {
+ if (for_parse) {
+ printer->Print("DO_(");
+ }
+ printer->Print(
+ "::google::protobuf::internal::WireFormatLite::$function$(\n",
+ "function", strict_function);
+ printer->Indent();
+ printer->Print(variables, parameters);
+ if (for_parse) {
+ printer->Print("::google::protobuf::internal::WireFormatLite::PARSE,\n");
+ } else {
+ printer->Print("::google::protobuf::internal::WireFormatLite::SERIALIZE,\n");
+ }
+ printer->Print("\"$full_name$\")", "full_name", field->full_name());
+ if (for_parse) {
+ printer->Print(")");
+ }
+ printer->Print(";\n");
+ printer->Outdent();
+ break;
+ }
+ case VERIFY: {
+ printer->Print(
+ "::google::protobuf::internal::WireFormat::$function$(\n",
+ "function", verify_function);
+ printer->Indent();
+ printer->Print(variables, parameters);
+ if (for_parse) {
+ printer->Print("::google::protobuf::internal::WireFormat::PARSE,\n");
+ } else {
+ printer->Print("::google::protobuf::internal::WireFormat::SERIALIZE,\n");
+ }
+ printer->Print("\"$full_name$\");\n", "full_name", field->full_name());
+ printer->Outdent();
+ break;
+ }
+ case NONE:
+ break;
+ }
+}
+
+void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
+ bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ io::Printer* printer) {
+ GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+ "VerifyUtf8String", "VerifyUTF8StringNamedField",
+ printer);
+}
+
+void GenerateUtf8CheckCodeForCord(const FieldDescriptor* field,
+ bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ io::Printer* printer) {
+ GenerateUtf8CheckCode(field, for_parse, variables, parameters,
+ "VerifyUtf8Cord", "VerifyUTF8CordNamedField",
+ printer);
+}
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_helpers.h b/src/google/protobuf/compiler/cpp/cpp_helpers.h
index 29c1f90b..985cb04c 100644
--- a/src/google/protobuf/compiler/cpp/cpp_helpers.h
+++ b/src/google/protobuf/compiler/cpp/cpp_helpers.h
@@ -202,11 +202,6 @@ inline bool HasGenericServices(const FileDescriptor* file) {
file->options().cc_generic_services();
}
-// Should string fields in this file verify that their contents are UTF-8?
-inline bool HasUtf8Verification(const FileDescriptor* file) {
- return file->options().optimize_for() != FileOptions::LITE_RUNTIME;
-}
-
// Should we generate a separate, super-optimized code path for serializing to
// flat arrays? We don't do this in Lite mode because we'd rather reduce code
// size.
@@ -270,6 +265,20 @@ inline bool SupportsArenas(const FieldDescriptor* field) {
bool IsAnyMessage(const FileDescriptor* descriptor);
bool IsAnyMessage(const Descriptor* descriptor);
+void GenerateUtf8CheckCodeForString(
+ const FieldDescriptor* field,
+ bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ io::Printer* printer);
+
+void GenerateUtf8CheckCodeForCord(
+ const FieldDescriptor* field,
+ bool for_parse,
+ const map<string, string>& variables,
+ const char* parameters,
+ io::Printer* printer);
+
} // namespace cpp
} // namespace compiler
} // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/cpp_map_field.cc b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
index a14d8986..25acc61b 100644
--- a/src/google/protobuf/compiler/cpp/cpp_map_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_map_field.cc
@@ -234,6 +234,20 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"}\n");
}
+ const FieldDescriptor* key_field =
+ descriptor_->message_type()->FindFieldByName("key");
+ if (key_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ key_field, true, variables_,
+ "entry->key().data(), entry->key().length(),\n", printer);
+ }
+ if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ value_field, true, variables_,
+ "entry->mutable_value()->data(),\n"
+ "entry->mutable_value()->length(),\n", printer);
+ }
+
// If entry is allocated by arena, its desctructor should be avoided.
if (SupportsArenas(descriptor_)) {
printer->Print(variables_,
@@ -261,7 +275,30 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" ::google::protobuf::internal::WireFormatLite::Write$stream_writer$(\n"
- " $number$, *entry, output);\n"
+ " $number$, *entry, output);\n");
+
+ printer->Indent();
+ printer->Indent();
+
+ const FieldDescriptor* key_field =
+ descriptor_->message_type()->FindFieldByName("key");
+ const FieldDescriptor* value_field =
+ descriptor_->message_type()->FindFieldByName("value");
+ if (key_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ key_field, false, variables_,
+ "it->first.data(), it->first.length(),\n", printer);
+ }
+ if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ value_field, false, variables_,
+ "it->second.data(), it->second.length(),\n", printer);
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
" }\n");
// If entry is allocated by arena, its desctructor should be avoided.
@@ -296,7 +333,29 @@ GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
" entry.reset($name$_.New$wrapper$(it->first, it->second));\n"
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$NoVirtualToArray(\n"
- " $number$, *entry, target);\n"
+ " $number$, *entry, target);\n");
+
+ printer->Indent();
+ printer->Indent();
+
+ const FieldDescriptor* key_field =
+ descriptor_->message_type()->FindFieldByName("key");
+ const FieldDescriptor* value_field =
+ descriptor_->message_type()->FindFieldByName("value");
+ if (key_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ key_field, false, variables_,
+ "it->first.data(), it->first.length(),\n", printer);
+ }
+ if (value_field->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ value_field, false, variables_,
+ "it->second.data(), it->second.length(),\n", printer);
+ }
+
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
" }\n");
// If entry is allocated by arena, its desctructor should be avoided.
diff --git a/src/google/protobuf/compiler/cpp/cpp_string_field.cc b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
index d1af6dda..6b0821a6 100644
--- a/src/google/protobuf/compiler/cpp/cpp_string_field.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_string_field.cc
@@ -367,25 +367,19 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, true, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
}
void StringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
printer->Print(variables_,
"::google::protobuf::internal::WireFormatLite::Write$declared_type$MaybeAliased(\n"
@@ -394,13 +388,10 @@ GenerateSerializeWithCachedSizes(io::Printer* printer) const {
void StringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
printer->Print(variables_,
"target =\n"
@@ -665,13 +656,10 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->mutable_$name$()));\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$().data(), this->$name$().length(),\n"
- " ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, true, variables_,
+ "this->$name$().data(), this->$name$().length(),\n", printer);
}
}
@@ -817,14 +805,12 @@ GenerateMergeFromCodedStream(io::Printer* printer) const {
printer->Print(variables_,
"DO_(::google::protobuf::internal::WireFormatLite::Read$declared_type$(\n"
" input, this->add_$name$()));\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$(this->$name$_size() - 1).data(),\n"
- " this->$name$(this->$name$_size() - 1).length(),\n"
- " ::google::protobuf::internal::WireFormat::PARSE,\n"
- " \"$full_name$\");\n");
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, true, variables_,
+ "this->$name$(this->$name$_size() - 1).data(),\n"
+ "this->$name$(this->$name$_size() - 1).length(),\n",
+ printer);
}
}
@@ -832,14 +818,13 @@ void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizes(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- "::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$(i).data(), this->$name$(i).length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ printer->Indent();
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
}
+ printer->Outdent();
printer->Print(variables_,
" ::google::protobuf::internal::WireFormatLite::Write$declared_type$(\n"
" $number$, this->$name$(i), output);\n"
@@ -850,14 +835,13 @@ void RepeatedStringFieldGenerator::
GenerateSerializeWithCachedSizesToArray(io::Printer* printer) const {
printer->Print(variables_,
"for (int i = 0; i < this->$name$_size(); i++) {\n");
- if (HasUtf8Verification(descriptor_->file()) &&
- descriptor_->type() == FieldDescriptor::TYPE_STRING) {
- printer->Print(variables_,
- " ::google::protobuf::internal::WireFormat::VerifyUTF8StringNamedField(\n"
- " this->$name$(i).data(), this->$name$(i).length(),\n"
- " ::google::protobuf::internal::WireFormat::SERIALIZE,\n"
- " \"$full_name$\");\n");
+ printer->Indent();
+ if (descriptor_->type() == FieldDescriptor::TYPE_STRING) {
+ GenerateUtf8CheckCodeForString(
+ descriptor_, false, variables_,
+ "this->$name$(i).data(), this->$name$(i).length(),\n", printer);
}
+ printer->Outdent();
printer->Print(variables_,
" target = ::google::protobuf::internal::WireFormatLite::\n"
" Write$declared_type$ToArray($number$, this->$name$(i), target);\n"