Skip to content

igzip: count held literals in the inflate look back distance check - #458

Open
ptweezy wants to merge 1 commit into
intel:masterfrom
ptweezy:igzip-inflate-pending-lits-lookback
Open

ptweezy wants to merge 1 commit into
intel:masterfrom
ptweezy:igzip-inflate-pending-lits-lookback

Conversation

@ptweezy

@ptweezy ptweezy commented Oct 21, 2026 •

Copy link
Copy Markdown

isal_inflate_stateless() returns ISAL_INVALID_LOOKBACK instead of ISAL_OUT_OVERFLOW for some valid streams when the output buffer is too small. When the buffer fills inside a lit/len table entry that holds literals and a length, the decoders keep the literals in write_overflow_lits and check the match distance against the output written so far. But the match starts after the held literals, so its distance counts them too: when the match copies from the first byte or two of the output, the distance is longer than the output written and the check fails.

Decoders

All decoders have the bug: x86 _01 and _04, aarch64, and C (used by arch=noarch and riscv64). On that path, which ends the call, this PR makes the x86 and aarch64 decoders lower their copy of start_out by the held literals, and the C decoder add them to the allowed distance. isal_inflate() is not affected, decoded output does not change, and no invalid stream is accepted.

Testing

  • igzip_rand_test inflates two hand-built streams ("a" or "ab", then a copy of 3) stateless into every smaller buffer. It fails without the fix and passes with it on x86 _04 and _01, arch=noarch, aarch64 and riscv64 under qemu, and natively on Windows.
  • make -f Makefile.unx check passes on x86 (_04 and _01), arch=noarch, aarch64 under qemu, and natively on Windows on a Ryzen 7 9800X3D (mingw-w64 x86_64 and i686).
  • Of 2,500 small streams inflated into every output size, master rejects 232 valid ones on every decoder and this PR none.

When the output buffer fills in the middle of a lit/len decode table
entry that holds literals followed by a length, the decoders keep the
literals in write_overflow_lits and still decode the length and its
distance, so that the copy can resume after the literals. The match
starts after the held literals, so its distance also counts them, but
the decoders check it against the output written so far. When the
distance is longer than that, which happens when the match copies from
the first byte or two of the output, isal_inflate_stateless() returns
ISAL_INVALID_LOOKBACK for a valid stream instead of ISAL_OUT_OVERFLOW.

Count the held literals in the check, in the x86, aarch64 and C
decoders. The x86 and aarch64 decoders lower their copy of start_out by
the number of held literals on that path, which ends the call, and the
C decoder adds them to the distance it allows.

Add two such streams to igzip_rand_test, "a" and "ab" each followed by
a copy of 3, and check that inflating them stateless into each smaller
output buffer returns ISAL_OUT_OVERFLOW with the start of the output.

Signed-off-by: Parker Loflin <parker@cronstable.dev>
@ptweezy
ptweezy force-pushed the igzip-inflate-pending-lits-lookback branch from 1452f39 to 6266dd2 Compare October 21, 2026 21:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant