Guard the FSE pass for the three symbols it writes

Both exhausted branches write a third symbol in the same pass that the
guard admitted for two. The Huffman weight decoder calls this with a
256-byte buffer and a limit of 256, so `at` reached 256 exactly, which
is one past the end, and a crafted weight stream turned that into an
IndexError rather than a refusal. A 53-byte input reproduces it, and
random mutation of a real tile found it independently.
This commit is contained in:
Tag 2026-09-21 23:09:25 -06:00
commit 489c898b14

View file

@ -207,7 +207,11 @@ int fseDecodeInterleaved(
var at = outStart;
while (true) {
if (at + 2 > outLimit) {
// Three, not two: both exhausted branches below write a third symbol in
// the same pass. Guarding for two let `at` reach outLimit exactly, which
// is one past the end of the caller's buffer, and a crafted weight
// stream turned that into an IndexError rather than a refusal.
if (at + 3 > outLimit) {
throw const ZstdException('FSE stream longer than its output allows');
}
out[at++] = symbol[state1];