Skip to content

harden(decode): fallible BufferBackend writes for direct-decode DoS protection #246

@polaz

Description

@polaz

Context

PR #245 introduced FrameDecoder::decode_to_slice with
UserSliceBackend writing directly into the caller's slice. The
backend's write methods (extend, extend_and_fill,
extend_from_within_unchecked) bounds-check via debug_assert! and
a release-mode assert!. Per-block produced tracking guards FCS
overflow AFTER each block completes.

Problem

Within a single Compressed block, the burst's per-symbol writes
hit the backend write methods in a tight loop. A malformed frame
that declares a small frame_content_size AND a Compressed block
whose payload expands past the declared size will cause the burst
to write past slice.len() and panic (assert! or slice
indexing). This is a DoS surface for adversarial input — should be
a structured FrameDecoderError instead.

Proposed fix

Extend BufferBackend to support fallible writes that return
Result<(), BackendOverflow>. The UserSliceBackend impl checks
remaining capacity on every write and returns an error instead of
panicking. FlatBuf / RingBuffer keep their current panic-free
behaviour (their Vec::reserve path handles growth).

Open design questions:

  • Do we add a parallel fallible API or migrate all backends?
  • Cost of per-write capacity check in the HUF burst hot path?
  • Could a coarser per-block pre-flight check work instead
    (e.g., refuse to enter direct path when produced + MAX_BLOCK_SIZE > content_size + WILDCOPY)?

Acceptance criteria

  • Malformed Compressed block with header FCS < expanded
    payload returns FrameDecoderError::FrameContentSizeMismatch
    from decode_to_slice instead of panicking.
  • Existing direct-path benchmarks regress by no more than 1%.
  • Existing tests remain green.

Workaround until fix

Callers handling untrusted input must use decode_all (which
routes through FlatBuf / RingBuffer and never panics on size
mismatches).

Part of the #244 perf roadmap.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2-mediumMedium priority — important improvementenhancementNew feature or requestperformancePerformance optimization

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions