Closed AxbB36 closed 3 months ago
Thanks for the detailed report! I'll take a look.
This issue also affects zip files that have a central directory offset of 0xffffffff. Here is a recipe to make a test case for that.
ffffffff-centralDirectoryOffset.zip.gz.gz (remove 2 layers of gzip)
# 216186 * 19867 = 0xffffffff - len("pad") - 30
dd if=/dev/zero bs=216186 count=19867 of=pad
touch -d '2019-05-01 00:00:00 UTC' pad
rm -f ffffffff-centralDirectoryOffset.zip
TZ=UTC zip -0 -X ffffffff-centralDirectoryOffset.zip pad
zipinfo -v
says:
The central directory is 49 (0000000000000031h) bytes long,
and its (expected) offset in bytes from the beginning of the zipfile
is 4294967295 (00000000FFFFFFFFh).
@AxbB36 This is fixed in yauzl version 3.1.1. I didn't make an automated test for this, because creating performant tests for large numbers is pretty difficult (see test/zip64.js), but i manually verified the test case you outlined in the OP works with the examples/dump.js
example.
This issue also affects zip files that have a central directory offset of 0xffffffff
Oh, I may not have fixed this issue. Are you getting an error expected zip64 extended information extra field
?
Oh, I may not have fixed this issue.
Ok, I fixed the entry handling as well in version 3.1.2. I think this issue is fully fixed now.
Create ffff.zip containing 65535 files as follows:
UnZip 6.0 can parse it:
But this yauzl program cannot:
The error message is:
yauzl interprets an
entryCount
of 0xffff (or acentralDirectoryOffset
of 0xffffffff) to mean that a Zip64 end of central directory locator must be present: https://github.com/thejoshwolfe/yauzl/blob/02a5ca69c7713f6d2897cc02f2acc1df21093e3d/index.js#L140-L142APPNOTE.TXT seems to say that the implication goes the other way: instead of 0xffff ⇒ Zip64, it is Zip64 ⇒ 0xffff; i.e., a value of 0xffff does not necessarily imply that Zip64 information must be present.
How some other implementations handle it
UnZip searches for a zip64 end of central directory locator unconditionally (whether or not there is a 0xffff or 0xffffffff), and does not error if the locator is not found. process.c:
find_ecrec
:process.c:
find_ecrec64
:Python zipfile also searches for a zip64 end of central directory locator unconditionally, and does not error if it does not find the expected signature: https://github.com/python/cpython/blob/v3.7.0/Lib/zipfile.py#L258-L259 https://github.com/python/cpython/blob/v3.7.0/Lib/zipfile.py#L282-L284 https://github.com/python/cpython/blob/v3.7.0/Lib/zipfile.py#L197-L202
Go archive/zip searches for a zip64 end of central directory locator only if
entryCount
is 0xffff, orcentralDirectoryOffset
is 0xffffffff, or the central directory size is 0xffffffff. It doesn't error if the locator is not found. https://github.com/golang/go/blob/go1.12.4/src/archive/zip/reader.go#L502-L511