mirror of
https://github.com/python/cpython.git
synced 2026-04-22 03:41:08 +00:00
bpo-34341: Fix appending to ZIP archives with the ZIP64 extension. (GH-8683)
(cherry picked from commit 9bdb7be482)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
e2c0aea670
commit
efdf316d23
3 changed files with 38 additions and 0 deletions
|
|
@ -750,6 +750,20 @@ def test_absolute_arcnames(self):
|
|||
with zipfile.ZipFile(TESTFN2, "r", zipfile.ZIP_STORED) as zipfp:
|
||||
self.assertEqual(zipfp.namelist(), ["absolute"])
|
||||
|
||||
def test_append(self):
|
||||
# Test that appending to the Zip64 archive doesn't change
|
||||
# extra fields of existing entries.
|
||||
with zipfile.ZipFile(TESTFN2, "w", allowZip64=True) as zipfp:
|
||||
zipfp.writestr("strfile", self.data)
|
||||
with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp:
|
||||
zinfo = zipfp.getinfo("strfile")
|
||||
extra = zinfo.extra
|
||||
with zipfile.ZipFile(TESTFN2, "a", allowZip64=True) as zipfp:
|
||||
zipfp.writestr("strfile2", self.data)
|
||||
with zipfile.ZipFile(TESTFN2, "r", allowZip64=True) as zipfp:
|
||||
zinfo = zipfp.getinfo("strfile")
|
||||
self.assertEqual(zinfo.extra, extra)
|
||||
|
||||
@requires_zlib
|
||||
class DeflateTestZip64InSmallFiles(AbstractTestZip64InSmallFiles,
|
||||
unittest.TestCase):
|
||||
|
|
|
|||
|
|
@ -159,6 +159,27 @@ class LargeZipFile(Exception):
|
|||
_CD64_DIRECTORY_SIZE = 8
|
||||
_CD64_OFFSET_START_CENTDIR = 9
|
||||
|
||||
_EXTRA_FIELD_STRUCT = struct.Struct('<HH')
|
||||
|
||||
def _strip_extra(extra, xids):
|
||||
# Remove Extra Fields with specified IDs.
|
||||
unpack = _EXTRA_FIELD_STRUCT.unpack
|
||||
modified = False
|
||||
buffer = []
|
||||
start = i = 0
|
||||
while i + 4 <= len(extra):
|
||||
xid, xlen = unpack(extra[i : i + 4])
|
||||
j = i + 4 + xlen
|
||||
if xid in xids:
|
||||
if i != start:
|
||||
buffer.append(extra[start : i])
|
||||
start = j
|
||||
modified = True
|
||||
i = j
|
||||
if not modified:
|
||||
return extra
|
||||
return b''.join(buffer)
|
||||
|
||||
def _check_zipfile(fp):
|
||||
try:
|
||||
if _EndRecData(fp):
|
||||
|
|
@ -1813,6 +1834,7 @@ def _write_end_record(self):
|
|||
min_version = 0
|
||||
if extra:
|
||||
# Append a ZIP64 field to the extra's
|
||||
extra_data = _strip_extra(extra_data, (1,))
|
||||
extra_data = struct.pack(
|
||||
'<HH' + 'Q'*len(extra),
|
||||
1, 8*len(extra), *extra) + extra_data
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
Appending to the ZIP archive with the ZIP64 extension no longer grows the
|
||||
size of extra fields of existing entries.
|
||||
Loading…
Add table
Add a link
Reference in a new issue