Skip to content

fix: drop unknown-magic items in cbor_decode instead of failing the document - #274

Open
thedavidmeister wants to merge 2 commits into
mainfrom
2026-08-25-issue-186
Open

fix: drop unknown-magic items in cbor_decode instead of failing the document#274
thedavidmeister wants to merge 2 commits into
mainfrom
2026-08-25-issue-186

Conversation

@thedavidmeister

Copy link
Copy Markdown
Contributor

Closes #186.

The adjudication

#186 asks, neutrally, whether cbor_decode is meant to be strict about unknown
magic numbers or to drop them. This PR takes drop, because the spec text is
one-sided on it:

  • Design goal: "Tooling can efficiently O(1) drop/ignore meta that it does not
    need or support decoding and parsing for". The per-item magic is named as
    exactly the mechanism for that — "a signal of intent for the payload
    without needing to first parse ... the entire payload".
  • "feel free to build systems and applications with your own numbers and
    interpretations", and the map structure exists "to facilitate future
    modifications to the conventions in this document in a way that tooling can
    adopt (or not) in a backwards compatible way".

Under the old behaviour neither is achievable: one third-party or newer-spec
item made the whole cbor-seq undecodable, so the supported items alongside it
were unreachable. The spec's magic number table already lists a number this
crate does not carry (Web data v1, the subject of #187), so a document a
conforming encoder can produce today is one this crate cannot read at all.

If a reviewer wants strict instead, then the spec text quoted above needs the
clarifying note #186 mentions, and this PR should be closed rather than
reworked.

What changed

RainMetaDocumentV1Item::cbor_decode peeks the magic under cbor map key 1 on
the already-parsed serde_cbor::Value and skips the item when it is not a
KnownMagic, then returns the rest.

  • The Deserialize visitor is untouched and still errors on an unknown magic.
    magic is typed KnownMagic, so a single item with an unknown magic has no
    representation; the drop belongs at the sequence level, which is where the
    spec puts it.
  • Only an unsigned integer under key 1 can be dropped. A missing, non-integer
    or negative key 1, and a sequence member that is not a map at all, still go
    through from_value and error exactly as before.
  • An input left with no items after the drop is Error::UnsupportedMeta,
    not Ok(vec![]). cbor_decode never returning an empty vec is load-bearing:
    AuthoringMetaV2::fetch_for_contract indexes [0] on the result.
  • The corrupt-meta guard drops track.len() != metas.len() (dropping items
    makes those lengths legitimately differ) and moves metas.is_empty() out to
    the new unsupported check. track.is_empty() and the end-offset equality
    stay, so empty input, a bare document prefix and trailing/truncated bytes are
    still CorruptMeta.

Overlap with sibling issues

All five open cbor_decode / KnownMagic issues were checked; this PR touches
one of them.

QA

  • Discriminating tests: test_cbor_decode_drops_unknown_magic_items,
    test_cbor_decode_unknown_magic_first_item,
    test_cbor_decode_all_unknown_magic_is_unsupported,
    test_cbor_decode_unknown_magic_then_truncated_is_corrupt — each fails on
    base, verified by mutating the skip back off (if true || !is_unknown_magic,
    which restores the base decode path): all four fail, and the mixed-document
    one fails with the issue's own repro,
    SerdeCborError(Message("unknown magic number")). The base-behaviour test
    they replace, test_cbor_decode_unknown_magic_errors, is deleted — it pinned
    the behaviour this PR changes.
    test_cbor_decode_non_integer_magic_errors and
    test_cbor_decode_non_map_item_errors do NOT fail on base (base also errors
    there); they are guard tests bounding the new drop path, mutation-killed
    below.

  • Mutations applied:

    1. if !is_unknown_magicif true || !is_unknown_magic (never drop) →
      killed by test_cbor_decode_drops_unknown_magic_items,
      test_cbor_decode_unknown_magic_first_item,
      test_cbor_decode_all_unknown_magic_is_unsupported,
      test_cbor_decode_unknown_magic_then_truncated_is_corrupt (4 failed).
    2. if metas.is_empty() { Err(UnsupportedMeta)? }if false && ...
      (no unsupported guard, returns Ok(vec![])) → killed by
      test_cbor_decode_all_unknown_magic_is_unsupported (1 failed).
    3. peek_magic's two _ => None arms → _ => Some(0) (treat a missing,
      non-integer or non-map key 1 as an unknown magic and drop it) → killed by
      test_cbor_decode_non_integer_magic_errors,
      test_cbor_decode_non_map_item_errors and the pre-existing
      test_cbor_decode_missing_magic_errors (3 failed).

    Each mutant was reverted and the suite re-run green after measuring.

  • Oracle: the metadata-v1 spec
    (https://github.com/rainlanguage/specs/blob/main/metadata-v1.md), quoted
    above, for the drop/ignore behaviour; the cbor spec for the expected bytes.
    Every fixture is handwritten byte by byte (handwritten_map_for emits
    a2 00 41 <payload> 01 1b <magic big-endian> from the cbor major types, not
    from cbor_encode), and the expected decoded values are built with
    plain_item, so no assertion is computed by the code under test.

  • Category check: the issue asks one question — strict vs drop — and reports one
    behaviour (a document mixing supported and unknown-magic items decodes to
    nothing). Covered: the mixed document now decodes to its supported items in
    order (unknown in the middle, and unknown first), and the all-unknown boundary
    the question implies is settled explicitly as UnsupportedMeta. The issue's
    fallback ask — "if the strict behaviour is intended, the spec text may deserve
    a clarifying note" — is not taken, because this PR adjudicates the other way;
    the spec repo is not this repo and no spec change is made here.

Verification: cargo test -p rain-metadata --lib meta:: — 237 passed, 0 failed.
cargo clippy --all-targets -- -D warnings and cargo fmt --check clean. The
full suite was not run locally by request; CI covers it.

🤖 Generated with Claude Code

baku-ccron and others added 2 commits August 25, 2026 16:51
…ocument

A cbor-seq mixing a supported meta with one carrying a magic this crate
does not know decoded to nothing at all, so the supported item was
unreachable. metadata-v1 makes the per-item magic the O(1) signal tooling
uses to drop/ignore meta it does not support, and states that others are
free to build with their own numbers.

An input left with no items after the drop is UnsupportedMeta, not an
empty vec: callers index the result.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 25, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 17 minutes.

View limit details

Limit details: You’ve used the included review currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9a1f7625-e435-4c41-a1e4-a332f91497c7

📥 Commits

Reviewing files that changed from the base of the PR and between 45ca96c and a0fab88.

📒 Files selected for processing (1)
  • crates/cli/src/meta/mod.rs

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

cbor_decode rejects entire documents containing unknown-magic items; spec expects unsupported metas to be droppable/ignorable

1 participant