mirror of
https://github.com/python/cpython.git
synced 2025-12-08 06:10:17 +00:00
Raise on overlapping file blocks
This commit is contained in:
parent
a788a001a4
commit
ae01b8cd69
2 changed files with 40 additions and 10 deletions
|
|
@ -2024,6 +2024,21 @@ def test_repack_data_descriptor_no_sig_and_zip64(self):
|
|||
# check file size
|
||||
self.assertEqual(os.path.getsize(TESTFN), expected_size)
|
||||
|
||||
def test_repack_overlapping_blocks(self):
|
||||
for ii in ([0], [1], [2]):
|
||||
with self.subTest(remove=ii):
|
||||
self._prepare_zip_from_test_files(TESTFN, self.test_files)
|
||||
with open(TESTFN, 'r+b') as fh:
|
||||
with zipfile.ZipFile(fh, 'a') as zh:
|
||||
zh.writestr('file.txt', b'dummy')
|
||||
for i in ii:
|
||||
zh.infolist()[i].file_size += 50
|
||||
zh.infolist()[i].compress_size += 50
|
||||
|
||||
with zipfile.ZipFile(TESTFN, 'a') as zh:
|
||||
with self.assertRaises(zipfile.BadZipFile):
|
||||
zh.repack()
|
||||
|
||||
@mock.patch('zipfile._ZipRepacker')
|
||||
def test_repack_closed(self, m_repack):
|
||||
self._prepare_zip_from_test_files(TESTFN, self.test_files)
|
||||
|
|
|
|||
|
|
@ -1452,25 +1452,40 @@ def _repack(self, zfile):
|
|||
# doesn't match the actual entry order
|
||||
filelist = sorted(zfile.filelist, key=lambda x: x.header_offset)
|
||||
|
||||
try:
|
||||
data_offset = filelist[0].header_offset
|
||||
except IndexError:
|
||||
data_offset = zfile.start_dir
|
||||
|
||||
# calculate the starting entry offset (bytes to skip)
|
||||
entry_offset = self._calc_initial_entry_offset(fp, data_offset)
|
||||
|
||||
# move file entries
|
||||
# calculate each entry size and validate
|
||||
entry_size_list = []
|
||||
used_entry_size_list = []
|
||||
for i, zinfo in enumerate(filelist):
|
||||
# get the total size of the entry
|
||||
try:
|
||||
offset = filelist[i + 1].header_offset
|
||||
except IndexError:
|
||||
offset = zfile.start_dir
|
||||
entry_size = offset - zinfo.header_offset
|
||||
|
||||
# may raise on an invalid local file header
|
||||
used_entry_size = self._calc_local_file_entry_size(fp, zinfo)
|
||||
|
||||
self._debug(3, i, zinfo.orig_filename, entry_size, used_entry_size)
|
||||
if used_entry_size > entry_size:
|
||||
raise BadZipFile(
|
||||
f"Overlapped entries: {zinfo.orig_filename!r} "
|
||||
f"(possible zip bomb)")
|
||||
|
||||
entry_size_list.append(entry_size)
|
||||
used_entry_size_list.append(used_entry_size)
|
||||
|
||||
# calculate the starting entry offset (bytes to skip)
|
||||
try:
|
||||
data_offset = filelist[0].header_offset
|
||||
except IndexError:
|
||||
data_offset = zfile.start_dir
|
||||
entry_offset = self._calc_initial_entry_offset(fp, data_offset)
|
||||
|
||||
# move file entries
|
||||
for i, zinfo in enumerate(filelist):
|
||||
entry_size = entry_size_list[i]
|
||||
used_entry_size = used_entry_size_list[i]
|
||||
|
||||
# update the header and move entry data to the new position
|
||||
if entry_offset > 0:
|
||||
old_header_offset = zinfo.header_offset
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue