Search code examples
delphizipdelphi-10-seattle

System.Zip.TZipFile.ExtractZipFile throws error with certain files. Why?


When extracting a ZIP file with System.Zip.TZipFile:

System.Zip.TZipFile.ExtractZipFile('C:\test.zip', 'R:\_TEST\');

for a specific ZIP file I get this error message box:

Stream read error.

Why?

The zip file which to reproduce the error, base64 encoded:

UEsDBC0ACAAIAHyDiEcAAAAA//////////8WABQATmV1ZXMgVGV4dGRva3VtZW50LnR4dAEAEAAA AAAAAAAAAAIAAAAAAAAAAwBQSwcIAAAAAAIAAAAAAAAAAAAAAAAAAABQSwECLQstAAgACAB8g4hH AAAAAP//////////FgA4AAAAAAABAAAAAAAAAAAATmV1ZXMgVGV4dGRva3VtZW50LnR4dAEAEAAA AAAAAAAAAAIAAAAAAAAACgAgAAAAAAABABgA1LFkAs0x0QHUsWQCzTHRAdSxZALNMdEBUEsFBgAA AAABAAEAfAAAAGIAAAAAAA==

Go to http://www.motobit.com/util/base64-decoder-encoder.asp

Decode this to your local storage as test.zip (don't change the character set)

The MD5 of the decoded binary file must be:

7357193E8F27FE1FB5AF2B8B6AF1F24C


Solution

  • Reference: The structure of a PKZip file by Florian Buchholz.

    Your ZIP file is stored using the ZIP64 extended variant of the format. The Delphi ZIP code does not support ZIP64.

    I deduced that the file was ZIP64 by looking at the local file header. The compressed and uncompressed size fields are both 0xffffffff. From the reference above:

    • Compressed size: if archive is in ZIP64 format, this filed is 0xffffffff and the length is stored in the extra field
    • Uncompressed size: if archive is in ZIP64 format, this filed is 0xffffffff and the length is stored in the extra field

    For the library to support ZIP64 it needs to detect these conditions and read the 64 bit values out of the additional headers. The Delphi code does not and attempts to read 0xffffffff bytes that are not there.

    You will need to find a different ZIP file library, one that supports ZIP64, in order to operate on such a ZIP file. Alternatively, you could side-step the problem if you could arrange that whatever creates the ZIP files uses the plain ZIP format.