]> granicus.if.org Git - python/commitdiff
Issue #9720: zipfile now writes correct local headers for files larger than 4 GiB.
authorSerhiy Storchaka <storchaka@gmail.com>
Mon, 14 Jan 2013 22:38:17 +0000 (00:38 +0200)
committerSerhiy Storchaka <storchaka@gmail.com>
Mon, 14 Jan 2013 22:38:17 +0000 (00:38 +0200)
1  2 
Lib/zipfile.py
Misc/NEWS

diff --cc Lib/zipfile.py
index 68051c8e130b35334c5599d5905a9bbb01e82f7e,32cf42c19870988c280ae88955849e17c8e225af..dcebf7211ef85ca93bf2cd0d156f0f7907b05c9f
@@@ -361,24 -341,22 +361,29 @@@ class ZipInfo (object)
  
          extra = self.extra
  
-         if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
-             # File is larger than what fits into a 4 byte integer,
-             # fall back to the ZIP64 extension
 +        min_version = 0
+         if zip64 is None:
+             zip64 = file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT
+         if zip64:
              fmt = '<HHQQ'
              extra = extra + struct.pack(fmt,
                      1, struct.calcsize(fmt)-4, file_size, compress_size)
+         if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
+             if not zip64:
+                 raise LargeZipFile("Filesize would require ZIP64 extensions")
+             # File is larger than what fits into a 4 byte integer,
+             # fall back to the ZIP64 extension
              file_size = 0xffffffff
              compress_size = 0xffffffff
 -            self.extract_version = max(45, self.extract_version)
 -            self.create_version = max(45, self.extract_version)
 +            min_version = ZIP64_VERSION
  
 +        if self.compress_type == ZIP_BZIP2:
 +            min_version = max(BZIP2_VERSION, min_version)
 +        elif self.compress_type == ZIP_LZMA:
 +            min_version = max(LZMA_VERSION, min_version)
 +
 +        self.extract_version = max(min_version, self.extract_version)
 +        self.create_version = max(min_version, self.create_version)
          filename, flag_bits = self._encodeFilenameFlags()
          header = struct.pack(structFileHeader, stringFileHeader,
                   self.extract_version, self.reserved, flag_bits,
@@@ -1301,16 -1140,23 +1306,19 @@@ class ZipFile
              zinfo.CRC = 0
              self.filelist.append(zinfo)
              self.NameToInfo[zinfo.filename] = zinfo
-             self.fp.write(zinfo.FileHeader())
+             self.fp.write(zinfo.FileHeader(False))
              return
  
 +        cmpr = _get_compressor(zinfo.compress_type)
          with open(filename, "rb") as fp:
              # Must overwrite CRC and sizes with correct data later
              zinfo.CRC = CRC = 0
              zinfo.compress_size = compress_size = 0
-             zinfo.file_size = file_size = 0
-             self.fp.write(zinfo.FileHeader())
+             # Compressed size can be larger than uncompressed size
+             zip64 = self._allowZip64 and \
+                     zinfo.file_size * 1.05 > ZIP64_LIMIT
+             self.fp.write(zinfo.FileHeader(zip64))
 -            if zinfo.compress_type == ZIP_DEFLATED:
 -                cmpr = zlib.compressobj(zlib.Z_DEFAULT_COMPRESSION,
 -                     zlib.DEFLATED, -15)
 -            else:
 -                cmpr = None
+             file_size = 0
              while 1:
                  buf = fp.read(1024 * 8)
                  if not buf:
diff --cc Misc/NEWS
index c444ed66b70bcb7171cdacc3d4450ec5e73997eb,4e892b2463da36d74bc569dda81513fc45708dbb..292138d067e3850ae77b5e2c8623a901e6618291
+++ b/Misc/NEWS
@@@ -147,11 -199,9 +147,14 @@@ Core and Builtin
  Library
  -------
  
+ - Issue #9720: zipfile now writes correct local headers for files larger than
+   4 GiB.
 +- Issue #16955: Fix the poll() method for multiprocessing's socket
 +  connections on Windows.
 +
 +- SSLContext.load_dh_params() now properly closes the input file.
 +
  - Issue #16829: IDLE printing no longer fails if there are spaces or other
    special characters in the file path.