Skip to content

refactor(mp4): let DecodeStyp delegate to DecodeStypSR - #588

Merged
tobbee merged 1 commit into
masterfrom
refactor/styp-delegate
Sep 13, 2026
Merged

tobbee merged 1 commit into
masterfrom
refactor/styp-delegate

Conversation

@tobbee

@tobbee tobbee commented Sep 13, 2026

Copy link
Copy Markdown
Collaborator

Follow-up to #581, as mentioned in the review there.

#581 correctly fixed the panic. This removes the duplication that made it need
an extra guard.

Why styp needed two guards and ftyp one

DecodeFtyp delegates to DecodeFtypSR, so one guard in the SR decoder covers
both paths. DecodeStyp instead built the box itself:

data, err := readBoxBody(r, hdr)
...
b := StypBox{data: data}
return &b, nil

so the guard had to be repeated. Delegating the way ftyp already does drops it
back to one guard per box type, 3 → 2.

The drift this fixes

The two decoders had already diverged in how they measure the payload:

ftyp:  sr.ReadBytes(hdr.payloadLen())
styp:  sr.ReadBytes(int(hdr.Size) - hdr.Hdrlen)

Equal today, but only payloadLen() stays correct for a box carrying an
extended (large) size, where the header is 16 bytes rather than 8 — the same
reasoning applied to esds in #587. Unified on payloadLen().

An observable inconsistency, not just cosmetics

For a styp that declares a short payload and is truncated, the two box
types disagreed on master for byte-identical input:

ftyp: decode ftyp pos 0: read box body length 2 does not match expected length 4
styp: decode styp pos 0: styp: payload too short: 4 < 8

ftyp reads the body first and so reports the truncation; styp guarded before
reading and reported the declared length. After this change both report the
truncation, which is what actually went wrong.

That is the one behaviour change here: a styp that is both short-declared and
truncated now reports the truncation rather than the short payload. Both are
errors, neither panics, and the result now matches ftyp.

Tests

TestFtypStypDecodeConsistency asserts that ftyp and styp report the same
thing for the same malformed input, across short-payload, truncated and
empty-payload cases. It fails on master:

--- FAIL: TestFtypStypDecodeConsistency/truncated
    ftyp and styp disagree on the same input:
      ftyp: decode TYPE pos 0: read box body length 2 does not match expected length 4
      styp: decode TYPE pos 0: TYPE: payload too short: 4 < 8

TestFtypStypShortPayload from #581 passes unchanged — the panic fix is intact.

Scope

No API change, so no CHANGELOG entry: the exported types, signatures and the
errors for well-formed input are all untouched.

This is the cheap part of the FStypBox idea on the old ftyp-styp-combined
branch — one decode body, fixes land once — without the breaking type merge.
The accessors (MajorBrand, CompatibleBrands, Info, …) are still duplicated;
they are pure reads over data and much less prone to drift than decoders that
carry guards.

🤖 Generated with Claude Code

DecodeStyp built the box itself instead of delegating the way DecodeFtyp
does, so the short-payload guard added in #581 had to be written twice
for styp and once for ftyp. Delegating removes the duplicate guard and
brings styp to the same dual-path shape as ftyp.

The two had already drifted: DecodeStypSR measured the payload as
int(hdr.Size)-hdr.Hdrlen where ftyp used hdr.payloadLen(). They are
equal today, but only one of them stays correct if a box ever carries an
extended size. Unify on payloadLen.

This also removes an observable inconsistency. For a styp that declares
a short payload and is also truncated, the reader path reported the
short payload while ftyp on the same input reported the truncation.
Both now report the truncation, which is what actually went wrong.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tobbee
tobbee merged commit 2f46f6e into master Sep 13, 2026
9 checks passed
@tobbee
tobbee deleted the refactor/styp-delegate branch September 13, 2026 20:30
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