Skip to content

encoding/prototext: enforce RecursionLimit in skipValue/skipMessageValue#67

Open
al4an444 wants to merge 1 commit intoprotocolbuffers:masterfrom
al4an444:fix/prototext-skipvalue-recursion-limit
Open

encoding/prototext: enforce RecursionLimit in skipValue/skipMessageValue#67
al4an444 wants to merge 1 commit intoprotocolbuffers:masterfrom
al4an444:fix/prototext-skipvalue-recursion-limit

Conversation

@al4an444
Copy link
Copy Markdown

@al4an444 al4an444 commented May 5, 2026

Summary

skipValue and skipMessageValue in encoding/prototext/decode.go are mutually recursive but do not check RecursionLimit. This allows deeply nested unknown fields to cause a stack overflow when DiscardUnknown is true, completely bypassing the recursion limit that unmarshalMessage and unmarshalMap enforce (added in commit 20262ed0).

Root Cause

  • skipValue (line 735) calls skipMessageValue on MessageOpen
  • skipMessageValue (line 770) calls skipValue on Name
  • Neither function decrements or checks opts.RecursionLimit
  • Reached via unmarshalMessage:206 when DiscardUnknown=true or ReservedNames().Has(name)

Reproduction

go test -v with a payload of 5000 nested unknown fields and RecursionLimit=10:

  • Skip path: accepted with err=nil (BUG - limit bypassed)
  • Known path (Struct/Value): correctly returns exceeded maximum recursion depth

With depth=5000000, the Go runtime aborts with fatal error: stack overflow (not recoverable via recover()).

Fix

Add the same RecursionLimit decrement idiom to both skipValue and skipMessageValue. Since decoder is passed by value, the decrement is naturally scoped per call chain.

This is a 6-line change (3 lines per function) using the exact same pattern as unmarshalMessage and unmarshalMap.

The skipValue and skipMessageValue functions are mutually recursive
but did not check RecursionLimit. This allowed deeply nested unknown
fields to cause a stack overflow when DiscardUnknown is true, bypassing
the recursion limit that unmarshalMessage and unmarshalMap enforce.

Add the same depth-tracking idiom to both skip helpers.

Fixes the incomplete fix in commit 20262ed.
@google-cla
Copy link
Copy Markdown

google-cla Bot commented May 5, 2026

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

@al4an444
Copy link
Copy Markdown
Author

al4an444 commented May 5, 2026

@googlebot I signed it!

@puellanivis
Copy link
Copy Markdown

Thank you for your interest into contributing to this project.

Unfortunately this project does not accept GitHub pull requests as the source-of-truth for this project is hosted at https://go.googlesource.com/protobuf. This project page on GitHub is a mirror of that other repository.

If you would like to contribute to this project, please follow the contribution guidelines for instructions on how to send a change. If the change you'd like to make is more substantial or introduces any new features, then it should first be discussed on the issue tracker.

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