8000 bpo-34341: Fix appending to ZIP archives with the ZIP64 extension. (G… · python/cpython@83a0985 · GitHub
[go: up one dir, main page]

Skip to content

Commit 83a0985

Browse files
bpo-34341: Fix appending to ZIP archives with the ZIP64 extension. (GH-8683)
(cherry picked from commit 9bdb7be) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent 1e7193b commit 83a0985

File tree

3 files changed

+38
-0
lines changed

3 files changed

+38
-0
lines changed

Lib/test/test_zipfile.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,20 @@ def test_absolute_arcnames(self):
718718
with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp:
719719
self.assertEqual(zipfp.namelist(), ["absolute"])
720720

721+
def test_append(self):
722+
# Test that appending to the Zip64 archive doesn't change
723+
# extra fields of existing entries.
724+
with zipfile.ZipFile(TESTFN2, "w", allowZip64=True) as zipfp:
725+
zipfp.writestr("strfile", self.data)
726+
with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp:
727+
zinfo = zipfp.getinfo("strfile")
728+
extra = zinfo.extra
729+
with zipfile.ZipFile(TESTFN2, "a", allowZip64=True) as zipfp:
730+
zipfp.writestr("strfile2", self.data)
731+
with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp:
732+
zinfo = zipfp.getinfo("strfile")
733+
self.assertEqual(zinfo.extra, extra)
734+
721735
@requires_zlib
722736
class DeflateTestZip64InSmallFiles(AbstractTestZip64InSmallFiles,
723737
unittest.TestCase):

Lib/zipfile.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,27 @@ class LargeZipFile(Exception):
164164
_CD64_DIRECTORY_SIZE = 8
165165
_CD64_OFFSET_START_CENTDIR = 9
166166

167+
_EXTRA_FIELD_STRUCT = struct.Struct('<HH')
168+
169+
def _strip_extra(extra, xids):
170+
# Remove Extra Fields with specified IDs.
171+
unpack = _EXTRA_FIELD_STRUCT.unpack
172+
modified = False
173+
buffer = []
174+
start = i = 0
175+
while i + 4 <= len(extra):
176+
xid, xlen = unpack(extra[i : i + 4])
177+
j = i + 4 + xlen
178+
if xid in xids:
179+
if i != start:
180+
buffer.append(extra[start : i])
181+
start = j
182+
modified = True
183+
i = j
184+
if not modified:
185+
return extra
186+
return b''.join(buffer)
187+
167188
def _check_zipfile(fp):
168189
try:
169190
if _EndRecData(fp):
@@ -1710,6 +1731,7 @@ def _write_end_record(self):
17101731
min_version = 0
17111732
if extra:
17121733
# Append a ZIP64 field to the extra's
1734+
extra_data = _strip_extra(extra_data, (1,))
17131735
extra_data = struct.pack(
17141736
'<HH' + 'Q'*len(extra),
17151737
1, 8*len(extra), *extra) + extra_data
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Appending to the ZIP archive with the ZIP64 extension no longer grows the
2+
size of extra fields of existing entries.

0 commit comments

Comments
 (0)
0