archive/zip: cannot parse file header with compressed size or local file header offset of 0xffffffff #31692
Labels
NeedsInvestigation
Someone must examine and confirm this is a valid issue and not a duplicate of an existing one.
Milestone
archive/zip misinterprets (I believe) APPNOTE.TXT 4.5.3, such that it wrongly requires a Zip64 Extended Information extra field to be present whenever the compressed size or local file header offset of a central directory header is exactly 0xffffffff. #14185 fixed the problem for the uncompressed size as a special case, but really there is nothing special about the uncompressed size and all three fields should be treated equally.
APPNOTE.TXT 4.5.3 says:
archive/zip interprets the statement as:
But that logic is backwards—it's an "only if", not an "if". I think the interpretation should rather be
In other words, 0xffffffff, by itself, is not a magic value that indicates special handling is required. It is the presence of a Zip64 Extended Information extra field that indicates special handling, and only then does the value 0xffffffff become significant. 0xffffffff is a perfectly valid field value to have in a non-Zip64 file.
I'm attaching a zip file that demonstrates the problem, ffffffff.zip.gz.gz. (It is gzipped twice to reduce the size of the attachment, but the gzip layers have nothing to do with the issue and you should remove them before testing.) The zip file was produced by Info-ZIP Zip 3.0 and contains 2 files, with a maximum compressed/uncompressed size of 0xffffffde and a maximum local file header offset of 0xffffffff. Zip has decided to write a non-Zip64 zip file, as none of the values exceeds 0xffffffff. Info-ZIP UnZip 6.00 can parse the file, but archive/zip cannot. The sample file was created as follows:
archive/zip doesn't have a problem if the local file header appears one byte earlier or later—the easiest way to test that is to use a 2- or 4-byte filename instead of "pad" in the recipe above. In the former case it's because the value is 0xfffffffe and in the latter case it's because the value is 0xffffffff but Zip64 information is present.
For corroboration, see the function
getZip64Data
in process.c of UnZip 6.00. It puts the Zip64 check outside the field value checks:Fixing this issue will allow removing the special case introduced in #14185 because it will be handled by the general case: a value of 0xffffffff means what it says, in the absence of a Zip64 extra field.
This issue is only a problem when reading a zip file, not when writing. archive/zip currently writes Zip64 information whenever a field is exactly 0xffffffff—that's probably a good idea for interoperability, even if it's not required. Compare Zip 3.0's strict inequality (function
putend
in zipfile.c):with archive/zip's non-strict inequality:
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes, I tried
go version devel +a62887aade Fri Apr 26 05:16:33 2019 +0000 linux/amd64
.What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
Put in ziplist.go:
Now run:
What did you expect to see?
What did you see instead?
The text was updated successfully, but these errors were encountered: