Test the guards that had no test

A sweep found no defect in the decoder and several in its tests. Three
of the five fixes could be reverted with all 103 tests still green.

The content size against expectedSize check is the worst of those,
because the .hgtz reader was simplified to rest on it: deleting
it left everything passing. Eleven cases cover it now. The RLE block
ceiling and the requirement that a frame be the whole input had none
either, so there are fixtures for a 13-byte frame that returns 2 MB, for
the same shape at exactly the maximum, for four bytes of junk after a
frame, and for a trailing skippable frame.

Two of the new fixtures close coverage gaps rather than guards. No legal
frame in the suite decoded a one-stream Huffman literals section, since
the only one present had to be refused. And the only test of hashing
each block as it lands rode on the zstd CLI being installed, so a
multi-block frame carrying a checksum is committed now.

Also replaces an assertion that constrained nothing. "Fills the buffer
exactly" checked that the count was over 256 and under 1024, which
passes with the guard at two, at three, or absent. The stream encodes
257 symbols, a buffer of 257 takes it and one of 256 does not.

And two comments that were wrong. The weight buffer is one larger than
the maximum on purpose, and shrinking it to 255 breaks 124 tests. A
caller passing expectedSize gets the exact check in addition to the
ceiling, not instead of it.
This commit is contained in:
Tag 2026-09-22 00:06:35 -06:00
commit 45cab0620f
2 changed files with 272 additions and 170 deletions

View file

@ -35,8 +35,11 @@ class ZstdDecoder {
/// skip it, and this is the bound that replaces it.
///
/// A caller that knows the exact size should pass [decode]'s `expectedSize`
/// instead and get an exact check rather than a ceiling. The `.hgtz` reader
/// knows it: a block is `height * width * 2`.
/// as well, and gets an exact check *in addition to* this ceiling rather
/// than instead of it: a frame declaring 70 MiB is refused here before the
/// two are ever compared. Raising it takes a `ZstdDecoder` of one's own,
/// since the top-level [zstdDecode] does not offer it. The `.hgtz` reader
/// knows its size: a block is `height * width * 2`.
static const int defaultMaxOutputSize = 64 * 1024 * 1024;
/// The ceiling this instance enforces. See [defaultMaxOutputSize].

View file

@ -14,6 +14,13 @@ class HuffmanTable {
/// The largest table log the format allows for literals.
static const int maxLog = 12;
/// One larger than the 255 weights a table may carry, deliberately.
///
/// `fseDecodeInterleaved` guards each pass for the three symbols its
/// exhausted branches can write, so a 255-weight stream whose final pass
/// writes two has to be able to start that pass at 253. Shrinking this to
/// 255 looks like a tightening and would refuse every 255-weight table,
/// which the real elevation containers are full of.
static const int _maxSymbols = 256;
/// One entry per table slot: the symbol in the low byte, the code length