| Index: third_party/protobuf/src/google/protobuf/text_format.cc
|
| diff --git a/third_party/protobuf/src/google/protobuf/text_format.cc b/third_party/protobuf/src/google/protobuf/text_format.cc
|
| index c0dfd53fd7b0c7360f3fada07cc23207f36723e9..5192eca9cadb217f68800336555a41d2ea716253 100644
|
| --- a/third_party/protobuf/src/google/protobuf/text_format.cc
|
| +++ b/third_party/protobuf/src/google/protobuf/text_format.cc
|
| @@ -234,7 +234,8 @@ class TextFormat::Parser::ParserImpl {
|
| bool allow_unknown_field,
|
| bool allow_unknown_enum,
|
| bool allow_field_number,
|
| - bool allow_relaxed_whitespace)
|
| + bool allow_relaxed_whitespace,
|
| + bool allow_partial)
|
| : error_collector_(error_collector),
|
| finder_(finder),
|
| parse_info_tree_(parse_info_tree),
|
| @@ -246,6 +247,7 @@ class TextFormat::Parser::ParserImpl {
|
| allow_unknown_field_(allow_unknown_field),
|
| allow_unknown_enum_(allow_unknown_enum),
|
| allow_field_number_(allow_field_number),
|
| + allow_partial_(allow_partial),
|
| had_errors_(false) {
|
| // For backwards-compatibility with proto1, we need to allow the 'f' suffix
|
| // for floats.
|
| @@ -391,6 +393,16 @@ class TextFormat::Parser::ParserImpl {
|
| DO(ConsumeAnyValue(full_type_name,
|
| message->GetDescriptor()->file()->pool(),
|
| &serialized_value));
|
| + if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) {
|
| + // Fail if any_type_url_field has already been specified.
|
| + if ((!any_type_url_field->is_repeated() &&
|
| + reflection->HasField(*message, any_type_url_field)) ||
|
| + (!any_value_field->is_repeated() &&
|
| + reflection->HasField(*message, any_value_field))) {
|
| + ReportError("Non-repeated Any specified multiple times.");
|
| + return false;
|
| + }
|
| + }
|
| reflection->SetString(
|
| message, any_type_url_field,
|
| string(prefix + full_type_name));
|
| @@ -513,18 +525,21 @@ class TextFormat::Parser::ParserImpl {
|
| }
|
|
|
| if (field->is_repeated() && TryConsume("[")) {
|
| - // Short repeated format, e.g. "foo: [1, 2, 3]"
|
| - while (true) {
|
| - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| - // Perform special handling for embedded message types.
|
| - DO(ConsumeFieldMessage(message, reflection, field));
|
| - } else {
|
| - DO(ConsumeFieldValue(message, reflection, field));
|
| - }
|
| - if (TryConsume("]")) {
|
| - break;
|
| + // Short repeated format, e.g. "foo: [1, 2, 3]".
|
| + if (!TryConsume("]")) {
|
| + // "foo: []" is treated as empty.
|
| + while (true) {
|
| + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| + // Perform special handling for embedded message types.
|
| + DO(ConsumeFieldMessage(message, reflection, field));
|
| + } else {
|
| + DO(ConsumeFieldValue(message, reflection, field));
|
| + }
|
| + if (TryConsume("]")) {
|
| + break;
|
| + }
|
| + DO(Consume(","));
|
| }
|
| - DO(Consume(","));
|
| }
|
| } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
|
| DO(ConsumeFieldMessage(message, reflection, field));
|
| @@ -718,7 +733,8 @@ class TextFormat::Parser::ParserImpl {
|
| value = SimpleItoa(int_value); // for error reporting
|
| enum_value = enum_type->FindValueByNumber(int_value);
|
| } else {
|
| - ReportError("Expected integer or identifier.");
|
| + ReportError("Expected integer or identifier, got: " +
|
| + tokenizer_.current().text);
|
| return false;
|
| }
|
|
|
| @@ -756,6 +772,20 @@ class TextFormat::Parser::ParserImpl {
|
| }
|
| return true;
|
| }
|
| + if (TryConsume("[")) {
|
| + while (true) {
|
| + if (!LookingAt("{") && !LookingAt("<")) {
|
| + DO(SkipFieldValue());
|
| + } else {
|
| + DO(SkipFieldMessage());
|
| + }
|
| + if (TryConsume("]")) {
|
| + break;
|
| + }
|
| + DO(Consume(","));
|
| + }
|
| + return true;
|
| + }
|
| // Possible field values other than string:
|
| // 12345 => TYPE_INTEGER
|
| // -12345 => TYPE_SYMBOL + TYPE_INTEGER
|
| @@ -831,7 +861,7 @@ class TextFormat::Parser::ParserImpl {
|
| return true;
|
| }
|
|
|
| - ReportError("Expected identifier.");
|
| + ReportError("Expected identifier, got: " + tokenizer_.current().text);
|
| return false;
|
| }
|
|
|
| @@ -851,7 +881,7 @@ class TextFormat::Parser::ParserImpl {
|
| // Returns false if the token is not of type STRING.
|
| bool ConsumeString(string* text) {
|
| if (!LookingAtType(io::Tokenizer::TYPE_STRING)) {
|
| - ReportError("Expected string.");
|
| + ReportError("Expected string, got: " + tokenizer_.current().text);
|
| return false;
|
| }
|
|
|
| @@ -869,13 +899,13 @@ class TextFormat::Parser::ParserImpl {
|
| // Returns false if the token is not of type INTEGER.
|
| bool ConsumeUnsignedInteger(uint64* value, uint64 max_value) {
|
| if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
|
| - ReportError("Expected integer.");
|
| + ReportError("Expected integer, got: " + tokenizer_.current().text);
|
| return false;
|
| }
|
|
|
| if (!io::Tokenizer::ParseInteger(tokenizer_.current().text,
|
| max_value, value)) {
|
| - ReportError("Integer out of range.");
|
| + ReportError("Integer out of range (" + tokenizer_.current().text + ")");
|
| return false;
|
| }
|
|
|
| @@ -902,10 +932,14 @@ class TextFormat::Parser::ParserImpl {
|
|
|
| DO(ConsumeUnsignedInteger(&unsigned_value, max_value));
|
|
|
| - *value = static_cast<int64>(unsigned_value);
|
| -
|
| if (negative) {
|
| - *value = -*value;
|
| + if ((static_cast<uint64>(kint64max) + 1) == unsigned_value) {
|
| + *value = kint64min;
|
| + } else {
|
| + *value = -static_cast<int64>(unsigned_value);
|
| + }
|
| + } else {
|
| + *value = static_cast<int64>(unsigned_value);
|
| }
|
|
|
| return true;
|
| @@ -915,18 +949,18 @@ class TextFormat::Parser::ParserImpl {
|
| // Accepts decimal numbers only, rejects hex or oct numbers.
|
| bool ConsumeUnsignedDecimalInteger(uint64* value, uint64 max_value) {
|
| if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
|
| - ReportError("Expected integer.");
|
| + ReportError("Expected integer, got: " + tokenizer_.current().text);
|
| return false;
|
| }
|
|
|
| const string& text = tokenizer_.current().text;
|
| if (IsHexNumber(text) || IsOctNumber(text)) {
|
| - ReportError("Expect a decimal number.");
|
| + ReportError("Expect a decimal number, got: " + text);
|
| return false;
|
| }
|
|
|
| if (!io::Tokenizer::ParseInteger(text, max_value, value)) {
|
| - ReportError("Integer out of range.");
|
| + ReportError("Integer out of range (" + text + ")");
|
| return false;
|
| }
|
|
|
| @@ -971,11 +1005,11 @@ class TextFormat::Parser::ParserImpl {
|
| *value = std::numeric_limits<double>::quiet_NaN();
|
| tokenizer_.Next();
|
| } else {
|
| - ReportError("Expected double.");
|
| + ReportError("Expected double, got: " + text);
|
| return false;
|
| }
|
| } else {
|
| - ReportError("Expected double.");
|
| + ReportError("Expected double, got: " + tokenizer_.current().text);
|
| return false;
|
| }
|
|
|
| @@ -1033,7 +1067,17 @@ class TextFormat::Parser::ParserImpl {
|
| DO(ConsumeMessageDelimiter(&sub_delimiter));
|
| DO(ConsumeMessage(value.get(), sub_delimiter));
|
|
|
| - value->AppendToString(serialized_value);
|
| + if (allow_partial_) {
|
| + value->AppendPartialToString(serialized_value);
|
| + } else {
|
| + if (!value->IsInitialized()) {
|
| + ReportError(
|
| + "Value of type \"" + full_type_name +
|
| + "\" stored in google.protobuf.Any has missing required fields");
|
| + return false;
|
| + }
|
| + value->AppendToString(serialized_value);
|
| + }
|
| return true;
|
| }
|
|
|
| @@ -1098,6 +1142,7 @@ class TextFormat::Parser::ParserImpl {
|
| const bool allow_unknown_field_;
|
| const bool allow_unknown_enum_;
|
| const bool allow_field_number_;
|
| + const bool allow_partial_;
|
| bool had_errors_;
|
| };
|
|
|
| @@ -1259,7 +1304,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input,
|
| overwrites_policy,
|
| allow_case_insensitive_field_, allow_unknown_field_,
|
| allow_unknown_enum_, allow_field_number_,
|
| - allow_relaxed_whitespace_);
|
| + allow_relaxed_whitespace_, allow_partial_);
|
| return MergeUsingImpl(input, output, &parser);
|
| }
|
|
|
| @@ -1276,7 +1321,7 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
|
| ParserImpl::ALLOW_SINGULAR_OVERWRITES,
|
| allow_case_insensitive_field_, allow_unknown_field_,
|
| allow_unknown_enum_, allow_field_number_,
|
| - allow_relaxed_whitespace_);
|
| + allow_relaxed_whitespace_, allow_partial_);
|
| return MergeUsingImpl(input, output, &parser);
|
| }
|
|
|
| @@ -1310,7 +1355,7 @@ bool TextFormat::Parser::ParseFieldValueFromString(
|
| ParserImpl::ALLOW_SINGULAR_OVERWRITES,
|
| allow_case_insensitive_field_, allow_unknown_field_,
|
| allow_unknown_enum_, allow_field_number_,
|
| - allow_relaxed_whitespace_);
|
| + allow_relaxed_whitespace_, allow_partial_);
|
| return parser.ParseField(field, output);
|
| }
|
|
|
|
|