IMPORT: slz/uslz: make the gzip FEXTRA field resumable
The FEXTRA optional header field is a 2-byte little endian length followed
by that many bytes to skip, and either part can be split across calls. The
code had a fast path and a slow path for each of the two parts, and used
buf_len=0 to mean "nothing pending" but that is also true right after the
fast path has consumed the length and found the payload incomplete.
Resuming from that point took the fast path again and read the length a
second time, from what were in fact the first two payload bytes. With the
payload being "ABCDEF", XLEN became 0x4241 = 16961 instead of 6, so the
decoder skipped 16963 bytes of deflate data and the stream was lost.
This could be reproduced with a gzip stream carrying FEXTRA, FNAME,
FCOMMENT and FHCRC: it failed for input chunk size from 2 to 8 and 12
to 17, i.e. whenever a call boundary happened to fall inside the FEXTRA
field.
Let's replace the four paths by one: always stash XLEN in the header
buffer and use buf_len as the count of bytes of the whole field
consumed so far, so that below 2 we are reading the length and above
we are skipping the payload. That is resumable at any byte and needs
no special case, at the cost of skipping the payload one byte at a
time, which is fine for a field that is rare and usually a few bytes
long.
tests/uslztest.sh goes from 1438/1514 to 1488/1514.
This is libslz upstream commit
f26fc5cd52abe47431832c807524262740d13450