Просмотр исходного кода

Add stack overflow protection for text format

It already exists for wire and json formats
Vitaly Buka 6 лет назад
Родитель
Сommit
6dcd81093c

+ 8 - 0
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_;
 };
 

+ 14 - 0
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_[];

+ 1 - 1
third_party/googletest

@@ -1 +1 @@
-Subproject commit 5ec7f0c4a113e2f18ac2c6cc7df51ad6afc24081
+Subproject commit c3bb0ee2a63279a803aaad956b9b26d74bf9e6e2