diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc index a72361e127..133944997c 100644 --- a/src/google/protobuf/text_format.cc +++ b/src/google/protobuf/text_format.cc @@ -262,6 +262,7 @@ class TextFormat::Parser::ParserImpl { allow_unknown_enum_(allow_unknown_enum), allow_field_number_(allow_field_number), allow_partial_(allow_partial), + recursion_budget_(io::CodedInputStream::GetDefaultRecursionLimit()), had_errors_(false) { // For backwards-compatibility with proto1, we need to allow the 'f' suffix // for floats. @@ -631,6 +632,10 @@ label_skip_parsing: bool ConsumeFieldMessage(Message* message, const Reflection* reflection, const FieldDescriptor* field) { + if (--recursion_budget_ < 0) { + ReportError("Message is too deep"); + return false; + } // If the parse information tree is not NULL, create a nested one // for the nested message. @@ -648,6 +653,8 @@ label_skip_parsing: delimiter)); } + ++recursion_budget_; + // Reset the parse information tree. parse_info_tree_ = parent; return true; @@ -1179,6 +1186,7 @@ label_skip_parsing: const bool allow_unknown_enum_; const bool allow_field_number_; const bool allow_partial_; + int recursion_budget_; bool had_errors_; }; diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc index 82a969ee1c..89bb164377 100644 --- a/src/google/protobuf/text_format_unittest.cc +++ b/src/google/protobuf/text_format_unittest.cc @@ -1810,6 +1810,20 @@ TEST_F(TextFormatParserTest, ParseDeprecatedField) { "\"deprecated_int32\"", 1, 21, &message, true); } +TEST_F(TextFormatParserTest, DeepRecursion) { + const char* format = "child: { $0 }"; + std::string input; + for (int i = 0; i < 100; ++i) + input = strings::Substitute(format, input); + + unittest::NestedTestAllTypes message; + ExpectSuccessAndTree(input, &message, nullptr); + + input = strings::Substitute(format, input); + ExpectMessage(input, + "Message is too deep", 1, 908, &message, false); +} + class TextFormatMessageSetTest : public testing::Test { protected: static const char proto_debug_string_[]; diff --git a/third_party/googletest b/third_party/googletest index 5ec7f0c4a1..c3bb0ee2a6 160000 --- a/third_party/googletest +++ b/third_party/googletest @@ -1 +1 @@ -Subproject commit 5ec7f0c4a113e2f18ac2c6cc7df51ad6afc24081 +Subproject commit c3bb0ee2a63279a803aaad956b9b26d74bf9e6e2