From f1a1394aecd9a4197ea131dd7b0aed53053f8c02 Mon Sep 17 00:00:00 2001 From: James Rich Date: Mon, 17 Aug 2026 16:54:39 -0500 Subject: [PATCH] docs: consolidate duplicate CHANGELOG sections before the 0.2.0 cut Three separate branches (#57 checksum, #58 dictionary-ID, #59 entropy/ multi-block) each added their own [Unreleased] entries and were rebased onto each other individually; the CHANGELOG merges left two duplicate artifacts: - Two separate "### Fixed" headers under [Unreleased], with the Dictionary_ID fix listed under both (once briefly, once in full) -- consolidated into one "### Fixed" section, keeping the more detailed wording, and reordered Added/Changed/Fixed/Notes to match this file's own established category order (see the [0.1.2] section). - A "Notes" bullet claiming "kzstd enforces no Dictionary_ID" as the reason wrong-dictionary decoding was silently wrong -- true before this release's own Dictionary_ID validation landed a few bullets above it, false by the time a reader reaches it. Rewritten to describe what the new check actually catches (proper-format dictionaries with a mismatched embedded ID) and what it still can't (raw-content dictionaries, or a frame with no declared ID). Signed-off-by: James Rich --- CHANGELOG.md | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 796dd3c..f1faf96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,18 +12,6 @@ for both dictionary-compressed and dictionary-free frames, plus dictionary-ID and content-checksum validation. No wire format or public-API changes, except where noted below. -### Fixed - -- The decoder now validates a frame's Content_Checksum when - `Content_Checksum_Flag` is set: it reads the trailing 4-byte XXH64 - checksum and throws `ZstdException` on a mismatch against the decoded - content, for ANY conformant frame — not just kzstd's own — so a real - `libzstd`-produced frame (checksums are on by default in the `zstd` CLI) - is no longer accepted with silently-corrupted content. -- The decoder now validates a frame's declared Dictionary_ID against the - supplied dictionary's own embedded ID (when both are present), throwing a - clear `ZstdException` on mismatch instead of a generic corruption error. - ### Added - `Zstd.compress` takes an opt-in `checksum: Boolean = false` parameter; when @@ -90,6 +78,12 @@ public-API changes, except where noted below. ### Fixed +- The decoder now validates a frame's Content_Checksum when + `Content_Checksum_Flag` is set: it reads the trailing 4-byte XXH64 + checksum and throws `ZstdException` on a mismatch against the decoded + content, for ANY conformant frame — not just kzstd's own — so a real + `libzstd`-produced frame (checksums are on by default in the `zstd` CLI) + is no longer accepted with silently-corrupted content. - The decoder now validates a frame's Dictionary_ID (RFC 8878 §3.1.1.3) against the supplied dictionary's own embedded Dictionary_ID (RFC 8878 §5), when both are present. Decoding a real libzstd frame (which sets a @@ -114,12 +108,15 @@ public-API changes, except where noted below. to raw literals. FSE-compressed weight descriptions and the 4-stream literals layout would lift those limits and are not implemented; neither affects decoding, which reads both. -- A dictionary-compressed frame's correctness now depends on the dictionary's +- A dictionary-compressed frame's correctness depends on the dictionary's entropy tables matching what the decoder is seeded with, not just its - content — decoding with the wrong dictionary was already silently wrong - before this work (kzstd enforces no `Dictionary_ID`), so this doesn't - introduce a new failure mode, just makes an existing one marginally more - sensitive. Use the same trained dictionary bytes on both ends, as always. + content. The Dictionary_ID check above catches this when both the frame and + the supplied dictionary are proper-format (embedded-ID) dictionaries with + different IDs; it can't catch a wrong raw-content dictionary (no embedded ID + to compare) or a frame with no declared Dictionary_ID (kzstd's own encoder + never sets one) — those still decode with whatever tables the wrong + dictionary provides, silently. Use the same trained dictionary bytes on + both ends, as always. ## [0.1.2]