diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py index faa7c990ca..e8d2c92ce8 100644 --- a/python/google/protobuf/internal/text_format_test.py +++ b/python/google/protobuf/internal/text_format_test.py @@ -841,6 +841,16 @@ class TextFormatParserTests(TextFormatBase): self.assertEqual(message.optional_nested_message.bb, 45) self.assertEqual(message.optional_int32, 123) + def testParseUnknownRepeatedMessage(self, message_module): + message = message_module.TestAllTypes() + text = ( + 'unknown_repeated: [{}]\n' + 'unknown_repeated2: [<>, {}]\n' + 'optional_nested_message { bb: 45 }' + ) + text_format.Parse(text, message, allow_unknown_field=True) + self.assertEqual(message.optional_nested_message.bb, 45) + def testParseBadEnumValue(self, message_module): message = message_module.TestAllTypes() text = 'optional_nested_enum: BARR' diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py index e8e1a30d72..680e38c235 100644 --- a/python/google/protobuf/text_format.py +++ b/python/google/protobuf/text_format.py @@ -1196,7 +1196,7 @@ class _Parser(object): ':') and not tokenizer.LookingAt('{') and not tokenizer.LookingAt('<'): self._DetectSilentMarker(tokenizer, immediate_message_type, field_name) if tokenizer.LookingAt('['): - self._SkipRepeatedFieldValue(tokenizer) + self._SkipRepeatedFieldValue(tokenizer, immediate_message_type) else: self._SkipFieldValue(tokenizer) else: @@ -1271,18 +1271,22 @@ class _Parser(object): not tokenizer.TryConsumeFloat()): raise ParseError('Invalid field value: ' + tokenizer.token) - def _SkipRepeatedFieldValue(self, tokenizer): + def _SkipRepeatedFieldValue(self, tokenizer, immediate_message_type): """Skips over a repeated field value. Args: tokenizer: A tokenizer to parse the field value. """ tokenizer.Consume('[') - if not tokenizer.LookingAt(']'): - self._SkipFieldValue(tokenizer) - while tokenizer.TryConsume(','): - self._SkipFieldValue(tokenizer) - tokenizer.Consume(']') + if not tokenizer.TryConsume(']'): + while True: + if tokenizer.LookingAt('<') or tokenizer.LookingAt('{'): + self._SkipFieldMessage(tokenizer, immediate_message_type) + else: + self._SkipFieldValue(tokenizer) + if tokenizer.TryConsume(']'): + break + tokenizer.Consume(',') class Tokenizer(object):