Skip to content

Set TextFormat default recursion limit to 100#26491

Open
gladiator9797 wants to merge 1 commit intoprotocolbuffers:mainfrom
gladiator9797:fix-textformat-default-recursion-limit
Open

Set TextFormat default recursion limit to 100#26491
gladiator9797 wants to merge 1 commit intoprotocolbuffers:mainfrom
gladiator9797:fix-textformat-default-recursion-limit

Conversation

@gladiator9797
Copy link

Summary

The TextFormat::Parser constructor initializes recursion_limit_ to std::numeric_limits<int>::max() (2,147,483,647) at text_format.cc:1803. This is inconsistent with:

  • Binary format parser: default 100 (CodedInputStream::default_recursion_limit_)
  • JSON parser: default 64-100
  • UPB binary decoder: default 100 (kUpb_WireFormat_DefaultDepthLimit)

A textproto with ~5,000-10,000 nested messages overflows the C stack before the recursion check ever triggers, causing SIGSEGV.

Fix

Change the default from std::numeric_limits<int>::max() to 100, matching CodedInputStream::default_recursion_limit_. Users who need a different limit can still call SetRecursionLimit().

Reproducer

// Parse deeply nested textproto
std::string textproto;
for (int i = 0; i < 10000; i++) textproto += "nested_type { ";
textproto += "name: \"x\"";
for (int i = 0; i < 10000; i++) textproto += " }";

DescriptorProto msg;
TextFormat::ParseFromString(textproto, &msg);  // SIGSEGV
$ ulimit -s 8192 && ./test
EXIT=139  (SIGSEGV - stack overflow)

Test plan

  • Verified crash with default limit (exit 139)
  • SetRecursionLimit() API still works for custom limits
  • Existing protobuf test suite passes

@zhangskz zhangskz added the 🅰️ safe for tests Mark a commit as safe to run presubmits over label Mar 20, 2026
@github-actions github-actions bot removed the 🅰️ safe for tests Mark a commit as safe to run presubmits over label Mar 20, 2026
The TextFormat::Parser constructor initializes recursion_limit_ to
std::numeric_limits<int>::max() (2,147,483,647). This is inconsistent
with the binary format parser (default 100) and the JSON parser (default
64-100). A textproto with ~5,000-10,000 nested messages overflows the C
stack before the recursion check triggers, causing SIGSEGV.

Change the default to 100, matching CodedInputStream::default_recursion_limit_.
Users who need a different limit can still call SetRecursionLimit().

Reproducer:
  Parse textproto with 10000 levels of nested_type { ... }
  -> SIGSEGV (exit 139) due to stack overflow
@gladiator9797 gladiator9797 force-pushed the fix-textformat-default-recursion-limit branch from 9cd1ebe to 8991e76 Compare March 21, 2026 04:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants