Skip to content

Commit bc865be

Browse files
committed
Add strict_descriptor option
1 parent 51c9254 commit bc865be

File tree

2 files changed

+42
-2
lines changed

2 files changed

+42
-2
lines changed

Lib/test/test_zipfile/test_core.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,6 +1950,45 @@ def test_repack_data_descriptor_no_sig(self):
19501950
# check file size
19511951
self.assertEqual(os.path.getsize(TESTFN), expected_size)
19521952

1953+
def test_repack_data_descriptor_no_sig_strict(self):
1954+
"""Should skip data descriptor without signature when `strict_descriptor` is set."""
1955+
for ii in ([0], [0, 1]):
1956+
with self.subTest(remove=ii):
1957+
# calculate the expected results
1958+
with open(TESTFN, 'wb') as fh:
1959+
with mock.patch('zipfile.struct.pack', side_effect=struct_pack_no_dd_sig):
1960+
self._prepare_zip_from_test_files(Unseekable(fh), self.test_files)
1961+
with zipfile.ZipFile(TESTFN, 'a') as zh:
1962+
for i in ii:
1963+
zh.remove(self.test_files[i][0])
1964+
expected_zinfos = [ComparableZipInfo(zi) for zi in zh.infolist()]
1965+
expected_size = os.path.getsize(TESTFN)
1966+
1967+
# do the removal and check the result
1968+
with open(TESTFN, 'wb') as fh:
1969+
with mock.patch('zipfile.struct.pack', side_effect=struct_pack_no_dd_sig):
1970+
zinfos = self._prepare_zip_from_test_files(Unseekable(fh), self.test_files)
1971+
with zipfile.ZipFile(TESTFN, 'a', self.compression) as zh:
1972+
# make sure data descriptor bit is really set (by making zipfile unseekable)
1973+
for zi in zh.infolist():
1974+
self.assertTrue(zi.flag_bits & 8, f'data descriptor flag not set: {zi.filename}')
1975+
1976+
for i in ii:
1977+
zh.remove(self.test_files[i][0])
1978+
zh.repack(strict_descriptor=True)
1979+
1980+
# check infolist
1981+
self.assertEqual(
1982+
[ComparableZipInfo(zi) for zi in zh.infolist()],
1983+
expected_zinfos,
1984+
)
1985+
1986+
# make sure the zip file is still valid
1987+
self.assertIsNone(zh.testzip())
1988+
1989+
# check file size
1990+
self.assertEqual(os.path.getsize(TESTFN), expected_size)
1991+
19531992
def test_repack_data_descriptor_no_sig_and_zip64(self):
19541993
"""Should correctly handle file entries using data descriptor without signature and zip64."""
19551994
for ii in ([0], [0, 1], [1], [2]):

Lib/zipfile/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1369,9 +1369,10 @@ def close(self):
13691369

13701370
class _ZipRepacker:
13711371
"""Class for ZipFile repacking."""
1372-
def __init__(self, *, chunk_size=2**20, debug=0):
1372+
def __init__(self, *, chunk_size=2**20, strict_descriptor=False, debug=0):
13731373
self.debug = debug # Level of printing: 0 through 3
13741374
self.chunk_size = chunk_size
1375+
self.strict_descriptor = strict_descriptor
13751376

13761377
def _debug(self, level, *msg):
13771378
if self.debug >= level:
@@ -1593,7 +1594,7 @@ def _validate_local_file_entry(self, fp, offset, end_offset):
15931594
)
15941595

15951596
dd = self._scan_data_descriptor(fp, pos, end_offset, zip64)
1596-
if dd is None:
1597+
if dd is None and not self.strict_descriptor:
15971598
dd = self._scan_data_descriptor_no_sig(fp, pos, end_offset, zip64)
15981599
if dd is None:
15991600
return None

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy