Skip to content

segment: the reader accepts a zero-length compressed payload the writer refuses to emit #1113

Description

@nikagra

Found while addressing review on #1074. No behaviour change proposed here — this is for triage.

The writer refuses a shape the reader accepts

segment.AppendCompressed will not emit a segment with compressedLen == 0 and a nonzero uncompressedLen (internal/segment/segment.go:386), rewriting it into the store-as-is fallback. The comment there says why:

a segment with compressedLen==0 and a nonzero uncompressedLen is undecodable by the peer, so guard against it for arbitrary Compressor implementations.

ReadCompressedPayload does not make the same judgement. It hands the empty wire payload to the compressor and accepts whatever comes back, provided the length matches. Measured against Conn.readContinuationSegment with a compressor that expands an empty source, PayloadLen=0, UncompressedLen=9 returns 9 bytes and a nil error — the reader accepts what the writer calls undecodable.

With the shipped lz4 it is unreachable: the decode yields nothing and the length check rejects it. So this is a contract question, not a live bug — should the reader reject the shape outright, on the same grounds the writer does, rather than deferring to the compressor?

lz4 does not reject an empty source

LZ4Compressor.AppendDecompressed (lz4/lz4.go:131) returns (dst, nil) for an empty src with a nonzero uncompressedLength: the uncompressedLength == 0 guard does not fire, and lz4.UncompressBlock short-circuits on len(src) == 0 and returns (0, nil). The mismatch is caught one level up, by the caller's length check.

That is fine as long as every caller has one, but it is undocumented and untested. lz4/lz4_test.go:136 covers a short source (invalid source or destination buffer too short); nothing covers an empty one.

Either a test pinning the current contract or an explicit error would do; the choice depends on the answer to the first question.

Refs: #1074 (comment)

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions