Skip to content

v4.7.6: Skip protobuf fields the message has no member for

Latest

Choose a tag to compare

@eyalz800 eyalz800 released this 09 Aug 21:24
An unrecognised field number was accepted without consuming the field, so
the reader carried on from the middle of it and read the remainder of the
message at the wrong offsets. Reserved field numbers behaved the same way,
since an empty member reads nothing.

The effect is not limited to malformed input. A writer that has added a
field sends `{a = 1, b = "AAAAAAAA"}` as `08 01 12 08 41 41 ...`; a reader
that only knows field 1 read the tag of field 2, skipped nothing, then took
`08` for a tag and `0x41` for its value, yielding `a = 65` and reporting
success. Whoever controls an unknown field also controls what the fields
after it decode to.

Skip the field instead, based on the wire type that is already in hand:
a varint is decoded and discarded, `fixed_64` and `fixed_32` advance by
eight and four bytes, and a length delimited field reads its length and
advances by it. Groups are deprecated and are not supported, so they are
rejected as a protocol error rather than guessed at. Every advance is
bounded against the remaining input, which keeps the position within the
archive.

Tests cover an older reader against a newer writer, an unknown field of
each wire type ahead of a known one, an unknown payload that would read as
a known field if it were mistaken for a tag stream, a reserved field
number, unknown fields that run past the end, an unsupported wire type, and
that field number zero is still rejected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dn1bSVJQe33FQ7uBGZpewf