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

Skip to content

Commit 1bdd946

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 1bdd946

3 files changed

Lines changed: 44 additions & 7 deletions

File tree

Lib/test/test_zipfile/test_core.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1080,6 +1080,43 @@ 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+
# check for file header
1093+
self.assertEqual(zipdata[:4], b"PK\x03\x04")
1094+
1095+
# pull out and check file information
1096+
(
1097+
vers, os, flags, comp, _, _, crc, csize, usize, fn_len,
1098+
ex_total_len, filename, ex_id, ex_len, ex_usize, ex_csize
1099+
) = struct.unpack("<BB2sHHHIIIHH8shhQQ", zipdata[4:58])
1100+
1101+
self.assertGreaterEqual(vers, zipfile.ZIP64_VERSION) # requires zip64 to extract
1102+
self.assertEqual(os, 0) # compatible with MS-DOS
1103+
self.assertEqual(flags, b"\x00\x00") # no flags
1104+
self.assertEqual(comp, 0) # compression method = stored
1105+
self.assertEqual(csize, 0xFFFFFFFF) # sizes are in zip64 extra
1106+
self.assertEqual(usize, 0xFFFFFFFF)
1107+
self.assertEqual(fn_len, 8) # filename len
1108+
self.assertEqual(ex_total_len, 20) # size of extra records
1109+
self.assertEqual(ex_id, 1) # Zip64 extra record
1110+
self.assertEqual(ex_len, 16) # 16 bytes of data
1111+
self.assertEqual(ex_usize, 1) # uncompressed size
1112+
self.assertEqual(ex_csize, 1) # compressed size
1113+
1114+
z = zipfile.ZipFile(io.BytesIO(zipdata))
1115+
zinfos = z.infolist()
1116+
self.assertEqual(len(zinfos), 1)
1117+
1118+
self.assertGreaterEqual(zinfos[0].extract_version, zipfile.ZIP64_VERSION) # requires zip64 to extract
1119+
10831120

10841121
@requires_zlib()
10851122
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 used
2+
to add files to them. Patch by Carey Metcalfe.

0 commit comments

Comments
 (0)