Skip to content

decompress: check content size when an empty last block ends the frame - #4885

Open
Huang-404-Q wants to merge 1 commit into
meta:devfrom
Huang-404-Q:fix/stream-empty-last-block-fcs
Open

Huang-404-Q wants to merge 1 commit into
meta:devfrom
Huang-404-Q:fix/stream-empty-last-block-fcs

Conversation

@Huang-404-Q

Copy link
Copy Markdown

ZSTD_decompressStream accepts a frame whose declared Frame_Content_Size does not match what it actually decoded, as long as the frame ends with an empty last block.

The frame used here is 19 bytes: a single segment, Frame_Content_Size = 1000000, then a 5-byte raw block plus an empty last raw block.

ZSTD_decompress      -> Data corruption detected
ZSTD_decompressStream-> 0 (frame complete), 5 bytes written

The streaming path returns early when the last block is empty and never reaches ZSTDds_decompressLastBlock, which is where the content-size check lives, so the check is skipped.

Fix

Run the same check at that early return:

RETURN_ERROR_IF(
    dctx->fParams.frameContentSize != ZSTD_CONTENTSIZE_UNKNOWN
 && dctx->decodedSize != dctx->fParams.frameContentSize,
    corruption_detected, "");

Test

New case in tests/zstreamtest.c (test 85, "reject empty last block that underflows frame content size") builds that frame and asserts the streaming API rejects it.

Without the change:

test 85 : reject empty last block that underflows frame content size :
  Error => empty last block bypassed the content size check
Error detected in Unit tests !

With it:

test 85 : reject empty last block that underflows frame content size : OK
138 fuzzer tests completed

A 20-second -T20s run also completes clean (631 tests).

ZSTD_decompressContinue() verifies decodedSize against the frame's
Frame_Content_Size only in the ZSTDds_decompressLastBlock path. An empty
last block terminates the frame earlier, in ZSTDds_decodeBlockHeader, so
ZSTD_decompressStream() accepted frames that decode fewer bytes than the
declared content size, while ZSTD_decompress() rejected them with
corruption_detected.

Perform the same check when an empty last block ends the frame, and add a
regression test to zstreamtest.
@meta-cla meta-cla Bot added the CLA Signed label Nov 2, 2026

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant