@@ -225,7 +225,9 @@ class TextFormat::Parser::ParserImpl {
225
225
bool allow_unknown_enum,
226
226
bool allow_field_number,
227
227
bool allow_relaxed_whitespace,
228
- bool allow_partial)
228
+ bool allow_partial,
229
+ int recursion_limit // backported from 3.8.0
230
+ )
229
231
: error_collector_(error_collector),
230
232
finder_ (finder),
231
233
parse_info_tree_(parse_info_tree),
@@ -238,7 +240,9 @@ class TextFormat::Parser::ParserImpl {
238
240
allow_unknown_enum_(allow_unknown_enum),
239
241
allow_field_number_(allow_field_number),
240
242
allow_partial_(allow_partial),
241
- had_errors_(false ) {
243
+ had_errors_(false ),
244
+ recursion_limit_(recursion_limit) // backported from 3.8.0
245
+ {
242
246
// For backwards-compatibility with proto1, we need to allow the 'f' suffix
243
247
// for floats.
244
248
tokenizer_.set_allow_f_after_float (true );
@@ -490,9 +494,9 @@ class TextFormat::Parser::ParserImpl {
490
494
if (TryConsume (" :" ) && !LookingAt (" {" ) && !LookingAt (" <" )) {
491
495
UnknownFieldSet* unknown_field = unknown_fields->AddGroup (unknown_fields->field_count ());
492
496
unknown_field->AddLengthDelimited (0 , field_name); // Add a field's name.
493
- return SkipFieldValue (unknown_field);
497
+ return SkipFieldValue (unknown_field, recursion_limit_ );
494
498
} else {
495
- return SkipFieldMessage (unknown_fields);
499
+ return SkipFieldMessage (unknown_fields, recursion_limit_ );
496
500
}
497
501
}
498
502
@@ -575,7 +579,14 @@ class TextFormat::Parser::ParserImpl {
575
579
}
576
580
577
581
// Skips the next field including the field's name and value.
578
- bool SkipField (UnknownFieldSet* unknown_fields) {
582
+ bool SkipField (UnknownFieldSet* unknown_fields, int recursion_limit) {
583
+
584
+ // OpenCV specific
585
+ if (--recursion_limit < 0 ) {
586
+ ReportError (" Message is too deep (SkipField)" );
587
+ return false ;
588
+ }
589
+
579
590
string field_name;
580
591
if (TryConsume (" [" )) {
581
592
// Extension name.
@@ -594,9 +605,9 @@ class TextFormat::Parser::ParserImpl {
594
605
if (TryConsume (" :" ) && !LookingAt (" {" ) && !LookingAt (" <" )) {
595
606
UnknownFieldSet* unknown_field = unknown_fields->AddGroup (unknown_fields->field_count ());
596
607
unknown_field->AddLengthDelimited (0 , field_name); // Add a field's name.
597
- DO (SkipFieldValue (unknown_field));
608
+ DO (SkipFieldValue (unknown_field, recursion_limit ));
598
609
} else {
599
- DO (SkipFieldMessage (unknown_fields));
610
+ DO (SkipFieldMessage (unknown_fields, recursion_limit ));
600
611
}
601
612
// For historical reasons, fields may optionally be separated by commas or
602
613
// semicolons.
@@ -608,6 +619,12 @@ class TextFormat::Parser::ParserImpl {
608
619
const Reflection* reflection,
609
620
const FieldDescriptor* field) {
610
621
622
+ // backported from 3.8.0
623
+ if (--recursion_limit_ < 0 ) {
624
+ ReportError (" Message is too deep" );
625
+ return false ;
626
+ }
627
+
611
628
// If the parse information tree is not NULL, create a nested one
612
629
// for the nested message.
613
630
ParseInfoTree* parent = parse_info_tree_;
@@ -624,18 +641,27 @@ class TextFormat::Parser::ParserImpl {
624
641
delimiter));
625
642
}
626
643
644
+ // backported from 3.8.0
645
+ ++recursion_limit_;
646
+
627
647
// Reset the parse information tree.
628
648
parse_info_tree_ = parent;
629
649
return true ;
630
650
}
631
651
632
652
// Skips the whole body of a message including the beginning delimiter and
633
653
// the ending delimiter.
634
- bool SkipFieldMessage (UnknownFieldSet* unknown_fields) {
654
+ bool SkipFieldMessage (UnknownFieldSet* unknown_fields, int recursion_limit) {
655
+ // OpenCV specific
656
+ if (--recursion_limit < 0 ) {
657
+ ReportError (" Message is too deep (SkipFieldMessage)" );
658
+ return false ;
659
+ }
660
+
635
661
string delimiter;
636
662
DO (ConsumeMessageDelimiter (&delimiter));
637
663
while (!LookingAt (" >" ) && !LookingAt (" }" )) {
638
- DO (SkipField (unknown_fields));
664
+ DO (SkipField (unknown_fields, recursion_limit ));
639
665
}
640
666
DO (Consume (delimiter));
641
667
return true ;
@@ -775,7 +801,14 @@ class TextFormat::Parser::ParserImpl {
775
801
return true ;
776
802
}
777
803
778
- bool SkipFieldValue (UnknownFieldSet* unknown_field) {
804
+ bool SkipFieldValue (UnknownFieldSet* unknown_field, int recursion_limit) {
805
+
806
+ // OpenCV specific
807
+ if (--recursion_limit < 0 ) {
808
+ ReportError (" Message is too deep (SkipFieldValue)" );
809
+ return false ;
810
+ }
811
+
779
812
if (LookingAtType (io::Tokenizer::TYPE_STRING)) {
780
813
while (LookingAtType (io::Tokenizer::TYPE_STRING)) {
781
814
tokenizer_.Next ();
@@ -785,9 +818,9 @@ class TextFormat::Parser::ParserImpl {
785
818
if (TryConsume (" [" )) {
786
819
while (true ) {
787
820
if (!LookingAt (" {" ) && !LookingAt (" <" )) {
788
- DO (SkipFieldValue (unknown_field));
821
+ DO (SkipFieldValue (unknown_field, recursion_limit ));
789
822
} else {
790
- DO (SkipFieldMessage (unknown_field));
823
+ DO (SkipFieldMessage (unknown_field, recursion_limit ));
791
824
}
792
825
if (TryConsume (" ]" )) {
793
826
break ;
@@ -1156,6 +1189,7 @@ class TextFormat::Parser::ParserImpl {
1156
1189
const bool allow_field_number_;
1157
1190
const bool allow_partial_;
1158
1191
bool had_errors_;
1192
+ int recursion_limit_; // backported from 3.8.0
1159
1193
};
1160
1194
1161
1195
#undef DO
@@ -1306,17 +1340,19 @@ class TextFormat::Printer::TextGenerator
1306
1340
TextFormat::Finder::~Finder () {
1307
1341
}
1308
1342
1309
- TextFormat::Parser::Parser (bool allow_unknown_field )
1343
+ TextFormat::Parser::Parser ()
1310
1344
: error_collector_(NULL ),
1311
1345
finder_ (NULL ),
1312
1346
parse_info_tree_(NULL ),
1313
1347
allow_partial_(false ),
1314
1348
allow_case_insensitive_field_(false ),
1315
- allow_unknown_field_(allow_unknown_field ),
1349
+ allow_unknown_field_(false ),
1316
1350
allow_unknown_enum_(false ),
1317
1351
allow_field_number_(false ),
1318
1352
allow_relaxed_whitespace_(false ),
1319
- allow_singular_overwrites_(false ) {
1353
+ allow_singular_overwrites_(false ),
1354
+ recursion_limit_(std::numeric_limits<int >::max())
1355
+ {
1320
1356
}
1321
1357
1322
1358
TextFormat::Parser::~Parser () {}
@@ -1335,7 +1371,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input,
1335
1371
overwrites_policy,
1336
1372
allow_case_insensitive_field_, allow_unknown_field_,
1337
1373
allow_unknown_enum_, allow_field_number_,
1338
- allow_relaxed_whitespace_, allow_partial_);
1374
+ allow_relaxed_whitespace_, allow_partial_, recursion_limit_ );
1339
1375
return MergeUsingImpl (input, output, &parser);
1340
1376
}
1341
1377
@@ -1353,7 +1389,7 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input,
1353
1389
ParserImpl::ALLOW_SINGULAR_OVERWRITES,
1354
1390
allow_case_insensitive_field_, allow_unknown_field_,
1355
1391
allow_unknown_enum_, allow_field_number_,
1356
- allow_relaxed_whitespace_, allow_partial_);
1392
+ allow_relaxed_whitespace_, allow_partial_, recursion_limit_ );
1357
1393
return MergeUsingImpl (input, output, &parser);
1358
1394
}
1359
1395
@@ -1388,7 +1424,7 @@ bool TextFormat::Parser::ParseFieldValueFromString(
1388
1424
ParserImpl::ALLOW_SINGULAR_OVERWRITES,
1389
1425
allow_case_insensitive_field_, allow_unknown_field_,
1390
1426
allow_unknown_enum_, allow_field_number_,
1391
- allow_relaxed_whitespace_, allow_partial_);
1427
+ allow_relaxed_whitespace_, allow_partial_, recursion_limit_ );
1392
1428
return parser.ParseField (field, output);
1393
1429
}
1394
1430
0 commit comments