Skip to content

Stop dropping the invalid byte 0xc1 in skip_nil and the header readers - #412

Merged
byroot merged 1 commit into
msgpack:masterfrom
wtn:skip
Oct 31, 2026
Merged

byroot merged 1 commit into
msgpack:masterfrom
wtn:skip

Conversation

@wtn

@wtn wtn commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Since 078020e, HEAD_BYTE_REQUIRED, the head_byte value for "nothing cached", is 0xc1, the one first byte the spec marks "(never used)". A 0xc1 read from the input is cached as the same value, so the next get_head_byte thinks the cache is empty and reads past it.

skip_nil returns false and leaves the 0xc1 cached. read_array_header and read_map_header raise UnexpectedTypeError and leave it cached too. The next read then skips the invalid byte:

u = MessagePack::Unpacker.new
u.feed("\xc1\x01".b)
u.skip_nil  #=> false
u.read      #=> 1, should raise MalformedFormatError

read and skip aren't affected; read_primitive rejects 0xc1 first.

Fix

HEAD_BYTE_REQUIRED is now 0x100. head_byte is an unsigned int and only ever receives 0..255 from the input, so the sentinel can't collide. It is only assigned in init, reset and reset_head_byte, and only compared in get_head_byte. JRuby has its own unpacker.

The JRuby decoder already behaves this way: read_array_header and read_map_header restore the buffer position on error, and skip_nil is not implemented there.

The new specs call skip_nil, read_array_header or read_map_header on "\xc1\x01" and check that the next read raises MalformedFormatError. Without the change they fail with expected MessagePack::MalformedFormatError but nothing was raised.

HEAD_BYTE_REQUIRED, the "no head byte buffered" sentinel, was 0xc1,
the one byte MessagePack leaves undefined. A real 0xc1 in the input
therefore looked like "nothing buffered", so skip_nil, read_array_header
and read_map_header let the next call read past it and the following
read returned the next object instead of raising MalformedFormatError.
Move the sentinel to 0x100, outside the range a byte can take.

Co-authored-by: Claude Mythos 5.1 <noreply@anthropic.com>
@byroot
byroot merged commit 7dabc7e into msgpack:master Oct 31, 2026
19 checks passed
@wtn
wtn deleted the skip branch October 31, 2026 09:06
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