zerkman / zzlib

zlib-compressed file depacking library in Lua
Do What The F*ck You Want To Public License
86 stars 21 forks source link

Fix Reading Literal Blocks #16

Closed rilipco closed 1 year ago

rilipco commented 1 year ago

This PR fixes the decoding of so called stored sections (aka literal blocks) which is done in the block_uncompressed function.

Previously, the block_uncompressed function directly accessed the buf field trying to read as many bytes as that section specified, which may be as many as 2^16 bytes (i.e. 64 KiB). However, the buf field holds at most 4 KiB, as read by the peekb function, causing out-of-bounds accesses, which in turn cause the following error:

$ dd if=/dev/random of=/dev/stdout bs=1 count=4096 | gzip -f > foo.gz
$ lua
> require("zzlib").gunzipf("foo.gz")
./inflate-bwo.lua:227: wrong number of arguments to 'insert'
stack traceback:
    [C]: in function 'table.insert'
    ./inflate-bwo.lua:227: in upvalue 'block_uncompressed'
    ./inflate-bwo.lua:240: in function 'inflate-bwo.main'
    ./zzlib.lua:82: in function <./zzlib.lua:56>
    (...tail calls...)
    [C]: in ?

Instead, this PR extracts the refilling of the buf field into a new next_byte function, which is then used by both the peekb and block_uncompressed function. Thus fixing the issue.

Notice, this issue has been noted with Lua 5.3 using the bwo implementation, specifically. Tho, it appears that the same algorithm is used in the bit32 implementation so it has been altered accordingly as well, tho the bit32 implementation has not been tested!

zerkman commented 1 year ago

Thanks a lot for this PR, spotting the bug and finding time to fix it. Well done! Merging it now.