Skip to content

test: FuzzUnmarshalBinary; audit entry for the decoder - #47

Merged
tannevaled merged 2 commits into
mainfrom
fuzz-unmarshal
Oct 11, 2026
Merged

tannevaled merged 2 commits into
mainfrom
fuzz-unmarshal

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

UnmarshalBinary (v0.10.0) decodes bytes that may come from a file, a notebook or the network. No fuzz target covered it, and the audit log had no entry for it.

FuzzUnmarshalBinary (marshal_fuzz_test.go) requires four things:

  • a refusal wraps ErrFormat;
  • nothing panics;
  • an accepted array re-encodes to no more bytes than it was decoded from, so a few bytes cannot claim a huge array;
  • re-encoding is a fixed point.

The seed corpus covers:

  • every dtype in several shapes, including (0, 2^40);
  • truncated headers;
  • the largest rank and dimensions a uvarint can express;
  • a non-minimal uvarint;
  • a bool byte other than 0 or 1.

Measured:

  • 11 million inputs in 3 minutes, no failure.
  • Negative control: I loosened the length check from != size to > size. The fuzzer failed in 0.09 s with "6 input bytes decoded to an array of 54 encoded bytes (bool [48])", so it can see the defect it guards against.
  • govulncheck ./... at go1.27.2 with go-fft v0.23.0 reports no vulnerabilities.

SECURITY.md gains the guarantee and an audit-log entry. There are no library changes: the decoder held.

🤖 Generated with Claude Code

tannevaled and others added 2 commits October 11, 2026 10:43
UnmarshalBinary (v0.10.0) takes bytes that may come from anywhere, and
nothing fuzzed it. The new target requires that a refusal wraps
ErrFormat, that nothing panics, that an accepted array re-encodes to no
more bytes than it was decoded from (so a few bytes cannot claim a huge
array), and that re-encoding is a fixed point.

11 million inputs, no failure. A copy accepting fewer bytes than the
shape needs fails it in 0.09 s (6 bytes decoded as 48 bools).
govulncheck at go1.27.2 with go-fft v0.23.0: none. SECURITY.md gains the
guarantee and the audit entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1<<40 does not fit the int of 386, arm and the other 32-bit targets, so
the test did not compile there. maxSize is the package's own bound on
every architecture. Compiled for linux/386, arm and mipsle, and run on
linux/386.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tannevaled
tannevaled merged commit 575b6f3 into main Oct 11, 2026
12 checks passed
@tannevaled
tannevaled deleted the fuzz-unmarshal branch October 11, 2026 09:09
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.

1 participant