Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit bd02290

Browse files
committed
Fix Zip64 extensions not being properly applied in some cases
This commit fixes an issue where adding a small file to a `ZipFile` object while forcing zip64 extensions causes an extra Zip64 record to be added to the zip, but doesn't update the `min_version` or file sizes. Fixes #103861
1 parent 86aa8a5 commit bd02290

3 files changed

Lines changed: 42 additions & 7 deletions

File tree

Lib/test/test_zipfile/test_core.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,41 @@ def test_generated_valid_zip64_extra(self):
10801080
self.assertEqual(zinfo.header_offset, expected_header_offset)
10811081
self.assertEqual(zf.read(zinfo), expected_content)
10821082

1083+
def test_force_zip64(self):
1084+
"""Test that forcing zip64 extensions correctly notes this in the zip file"""
1085+
data = io.BytesIO()
1086+
with zipfile.ZipFile(data, mode="w", allowZip64=True) as zf:
1087+
with zf.open("text.txt", mode="w", force_zip64=True) as zi:
1088+
zi.write(b"_")
1089+
1090+
zipdata = data.getvalue()
1091+
1092+
# pull out and check zip information
1093+
(
1094+
header, vers, os, flags, comp, csize, usize, fn_len,
1095+
ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize, cd_sig
1096+
) = struct.unpack("<4sBBHH8xIIHH8shhQQx4s", zipdata[:63])
1097+
1098+
self.assertEqual(header, b"PK\x03\x04") # local file header
1099+
self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract
1100+
self.assertEqual(os, 0) # compatible with MS-DOS
1101+
self.assertEqual(flags, 0) # no flags
1102+
self.assertEqual(comp, 0) # compression method = stored
1103+
self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra
1104+
self.assertEqual(usize, 0xFFFFFFFF)
1105+
self.assertEqual(fn_len, 8) # filename len
1106+
self.assertEqual(ex_total_len, 20) # size of extra records
1107+
self.assertEqual(ex_id, 1) # Zip64 extra record
1108+
self.assertEqual(ex_len, 16) # 16 bytes of data
1109+
self.assertEqual(ex_usize, 1) # uncompressed size
1110+
self.assertEqual(ex_csize, 1) # compressed size
1111+
1112+
z = zipfile.ZipFile(io.BytesIO(zipdata))
1113+
zinfos = z.infolist()
1114+
self.assertEqual(len(zinfos), 1)
1115+
1116+
self.assertGreaterEqual(zinfos[0].extract_version, zipfile.ZIP64_VERSION) # requires zip64 to extract
1117+
10831118

10841119
@requires_zlib()
10851120
class DeflateTestZip64InSmallFiles(AbstractTestZip64InSmallFiles,

Lib/zipfile/__init__.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -455,17 +455,15 @@ def FileHeader(self, zip64=None):
455455
extra = self.extra
456456

457457
min_version = 0
458-
if zip64 is None:
459-
zip64 = file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT
458+
if (file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT):
459+
if zip64 is None:
460+
zip64 = True
461+
elif not zip64:
462+
raise LargeZipFile("Filesize would require ZIP64 extensions")
460463
if zip64:
461464
fmt = '<HHQQ'
462465
extra = extra + struct.pack(fmt,
463466
1, struct.calcsize(fmt)-4, file_size, compress_size)
464-
if file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT:
465-
if not zip64:
466-
raise LargeZipFile("Filesize would require ZIP64 extensions")
467-
# File is larger than what fits into a 4 byte integer,
468-
# fall back to the ZIP64 extension
469467
file_size = 0xffffffff
470468
compress_size = 0xffffffff
471469
min_version = ZIP64_VERSION
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix ``zipfile.Zipfile`` creating invalid zip files when ``force_zip64`` was
2+
used to add files to them. Patch by Carey Metcalfe.

0 commit comments

Comments
 (0)