| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
The mcpack2pb parser recurses once per nesting level of the incoming object/array. A message with an excessively deep recursive structure makes the recursion grow unbounded and the stack overflow, crashing the process. The serializer already enforces MAX_DEPTH=128, but the parse path never checked it. Thread the nesting depth through UnparsedValue and the iterators, and fail the parse once the depth exceeds MAX_DEPTH, mirroring the serializer. Deeply nested but legitimate messages keep working.
There was a problem hiding this comment.
This PR adds a recursion/nesting depth limit to the mcpack2pb parser to prevent unbounded recursion on deeply nested mcpack objects/arrays (stack overflow), aligning parser behavior with the existing serializer depth cap.
Changes:
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/mcpack2pb/parser.h | Adds depth plumbing to UnparsedValue, ObjectIterator, and ArrayIterator declarations and constructors. |
| src/mcpack2pb/parser-inl.h | Enforces MAX_DEPTH in iterator init() and threads depth through as_object() / as_array(). |
| src/mcpack2pb/parser.cpp | Propagates iterator depth into yielded UnparsedValue items during iteration. |
| test/brpc_mcpack2pb_unittest.cpp | Adds regression tests ensuring deep nesting is rejected without stack overflow (small-stack thread). |
src/mcpack2pb/parser.h:170
// Parse `n' bytes from `stream' as fields of an object.
// `depth' is the nesting level of the object; the top-level object
// starts at 0 and each nested iterator adds 1. Input nested deeper
// than MAX_DEPTH is rejected to avoid stack overflow on unbounded
// recursion (CWE-674), mirroring the serializer's limit.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Sorry, something went wrong.
Make the depth semantics in parser.h consistent with the implementation (UnparsedValue::depth counts the containers the value is nested in, iterators add one), document that the 3-arg set() intentionally keeps the depth, and trim the unit test: parse a payload a few levels beyond MAX_DEPTH instead of 16384 levels, which is equally effective, much faster and avoids O(depth^2) payload construction. Also destroy the pthread attribute on every path.
There was a problem hiding this comment.
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
Suppressed comments (1)src/mcpack2pb/parser.h:221
class ArrayIterator {
public:
typedef UnparsedValue Field;
ArrayIterator(InputStream* stream, size_t size, size_t depth = 0)
{ init(stream, size, depth); }
explicit ArrayIterator(UnparsedValue& value)
{ init(value.stream(), value.size(), value.depth() + 1); }
Sorry, something went wrong.
Default the stream-based ObjectIterator/ArrayIterator depth to 1 so the top-level container always has depth 1 whether built from a value (depth+1) or directly from a stream, matching the documented semantics and keeping the MAX_DEPTH guard effective for all constructor paths. In the unit test, destroy the pthread attribute on a single shared path right after create (when it is still valid and no longer needed), instead of unconditionally calling pthread_attr_destroy which would be undefined behavior if pthread_attr_init failed.
| Back | FazBrowse Home | New Git URL |
What problem does this PR solve?
Problem Summary:
The mcpack2pb parser (used by nshead_mcpack / ubrpc / public_pbrpc
requests) has no limit on the nesting depth of the input object/array.
For a protobuf message that references itself (e.g. a repeated
message field), the generated parser recurses once per nesting level,
so an input nested deep enough makes the recursion grow unbounded and
overflow the stack, crashing the process. The serializer has enforced
MAX_DEPTH (src/mcpack2pb/field_type.h) since the beginning, the
parser just never did.
What is changed and the side effects?
Changed:
and the ObjectIterator / ArrayIterator constructors.
exceeds MAX_DEPTH (128), exactly like the serializer already does,
so that the recursion stops at a bounded level instead of exhausting
the stack.
without crashing) and a moderately-nested one (parsed normally).
The depth limit is enforced on the iterator level, so existing code
generated by protoc-gen-mcpack is protected without regeneration:
no generated-code API is changed.
Side effects:
Parsing now fails for mcpack input nested deeper than 128 levels
(the same limit the serializer already applies). Such input is
abnormal for any real workload, roughly matching
json2pb_max_recursion_depth (100) used by the JSON parser.
Performance effects: none (one integer compare per iterator).
Breaking backward compatibility: no.
Check List: