diff --git a/Lib/test/test_zipfile/test_core.py b/Lib/test/test_zipfile/test_core.py index 4f20209927e7b3d..d166d226903e6d8 100644 --- a/Lib/test/test_zipfile/test_core.py +++ b/Lib/test/test_zipfile/test_core.py @@ -1189,6 +1189,56 @@ def test_generated_valid_zip64_extra(self): self.assertEqual(zinfo.header_offset, expected_header_offset) self.assertEqual(zf.read(zinfo), expected_content) + def test_generated_valid_zip64_extra_in_local_entry(self): + """Should not write duplicated zip64 fields to the local file entry.""" + fh = io.BytesIO() + with zipfile.ZipFile(fh, 'w') as zh: + zinfo = zipfile.ZipInfo('strfile') + zinfo.extra = ( + # zip64 (should be stripped) + b'\x01\x00\x10\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00' + + # invalid tail + b'zzz' + ) + zh.writestr(zinfo, self.data) + + fh.seek(0) + fh.seek(zinfo.header_offset) + entry = fh.read(zh.start_dir - zinfo.header_offset - zinfo.compress_size) + header = struct.unpack_from(zipfile.structFileHeader, entry) + extra_bytes = entry[-header[zipfile._FH_EXTRA_FIELD_LENGTH]:] + self.assertEqual(extra_bytes, ( + b'\x01\x00\x10\x00' + b'!e\x00\x00\x00\x00\x00\x00' + b'!e\x00\x00\x00\x00\x00\x00' + b'zzz' + )) + + # should strip zip64 field if zip64 not used + fh = io.BytesIO() + with zipfile.ZipFile(fh, 'w') as zh: + zinfo = zipfile.ZipInfo('strfile') + zinfo.extra = ( + # zip64 (should be stripped) + b'\x01\x00\x10\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00' + b'\x00\x00\x00\x00\x00\x00\x00\x00' + + # invalid tail + b'zzz' + ) + zh.writestr(zinfo, 'foo') + + fh.seek(0) + fh.seek(zinfo.header_offset) + entry = fh.read(zh.start_dir - zinfo.header_offset - zinfo.compress_size) + header = struct.unpack_from(zipfile.structFileHeader, entry) + extra_bytes = entry[-header[zipfile._FH_EXTRA_FIELD_LENGTH]:] + self.assertEqual(extra_bytes, b'zzz') + def test_force_zip64(self): """Test that forcing zip64 extensions correctly notes this in the zip file""" diff --git a/Lib/zipfile/__init__.py b/Lib/zipfile/__init__.py index 418933a2e8d9e87..00a7eb06ab3fdaf 100644 --- a/Lib/zipfile/__init__.py +++ b/Lib/zipfile/__init__.py @@ -541,7 +541,13 @@ def FileHeader(self, zip64=None): compress_size = self.compress_size file_size = self.file_size - extra = self.extra + # Strip extra fields that should not exist in the local entry or should + # be determined later. + extra = _Extra.strip(self.extra, ( + 0x0001, # Zip64 + 0x0017, # Strong Encryption Header + 0x6375, # Unicode Comment + )) min_version = 0 if zip64 is None: @@ -550,8 +556,13 @@ def FileHeader(self, zip64=None): zip64 = file_size > ZIP64_LIMIT or compress_size > ZIP64_LIMIT if zip64: fmt = '` contained them. +