@@ -859,6 +859,8 @@ def make_zip64_file(
859
859
self , file_size_64_set = False , file_size_extra = False ,
860
860
compress_size_64_set = False , compress_size_extra = False ,
861
861
header_offset_64_set = False , header_offset_extra = False ,
862
+ extensible_data = b'' ,
863
+ end_of_central_dir_size = None , offset_to_end_of_central_dir = None ,
862
864
):
863
865
"""Generate bytes sequence for a zip with (incomplete) zip64 data.
864
866
@@ -912,6 +914,12 @@ def make_zip64_file(
912
914
913
915
central_dir_size = struct .pack ('<Q' , 58 + 8 * len (central_zip64_fields ))
914
916
offset_to_central_dir = struct .pack ('<Q' , 50 + 8 * len (local_zip64_fields ))
917
+ if end_of_central_dir_size is None :
918
+ end_of_central_dir_size = 44 + len (extensible_data )
919
+ if offset_to_end_of_central_dir is None :
920
+ offset_to_end_of_central_dir = (108
921
+ + 8 * len (local_zip64_fields )
922
+ + 8 * len (central_zip64_fields ))
915
923
916
924
local_extra_length = struct .pack ("<H" , 4 + 8 * len (local_zip64_fields ))
917
925
central_extra_length = struct .pack ("<H" , 4 + 8 * len (central_zip64_fields ))
@@ -940,14 +948,17 @@ def make_zip64_file(
940
948
+ filename
941
949
+ central_extra
942
950
# Zip64 end of central directory
943
- + b"PK\x06 \x06 ,\x00 \x00 \x00 \x00 \x00 \x00 \x00 -\x00 -"
944
- + b"\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 "
951
+ + b"PK\x06 \x06 "
952
+ + struct .pack ('<Q' , end_of_central_dir_size )
953
+ + b"-\x00 -\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 "
945
954
+ b"\x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 \x00 \x00 "
946
955
+ central_dir_size
947
956
+ offset_to_central_dir
957
+ + extensible_data
948
958
# Zip64 end of central directory locator
949
- + b"PK\x06 \x07 \x00 \x00 \x00 \x00 l\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 "
950
- + b"\x00 \x00 \x00 "
959
+ + b"PK\x06 \x07 \x00 \x00 \x00 \x00 "
960
+ + struct .pack ('<Q' , offset_to_end_of_central_dir )
961
+ + b"\x01 \x00 \x00 \x00 "
951
962
# end of central directory
952
963
+ b"PK\x05 \x06 \x00 \x00 \x00 \x00 \x01 \x00 \x01 \x00 :\x00 \x00 \x00 2\x00 "
953
964
+ b"\x00 \x00 \x00 \x00 "
@@ -978,6 +989,7 @@ def test_bad_zip64_extra(self):
978
989
with self .assertRaises (zipfile .BadZipFile ) as e :
979
990
zipfile .ZipFile (io .BytesIO (missing_file_size_extra ))
980
991
self .assertIn ('file size' , str (e .exception ).lower ())
992
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_file_size_extra )))
981
993
982
994
# zip64 file size present, zip64 compress size present, one field in
983
995
# extra, expecting two, equals missing compress size.
@@ -989,6 +1001,7 @@ def test_bad_zip64_extra(self):
989
1001
with self .assertRaises (zipfile .BadZipFile ) as e :
990
1002
zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
991
1003
self .assertIn ('compress size' , str (e .exception ).lower ())
1004
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
992
1005
993
1006
# zip64 compress size present, no fields in extra, expecting one,
994
1007
# equals missing compress size.
@@ -998,6 +1011,7 @@ def test_bad_zip64_extra(self):
998
1011
with self .assertRaises (zipfile .BadZipFile ) as e :
999
1012
zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
1000
1013
self .assertIn ('compress size' , str (e .exception ).lower ())
1014
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
1001
1015
1002
1016
# zip64 file size present, zip64 compress size present, zip64 header
1003
1017
# offset present, two fields in extra, expecting three, equals missing
@@ -1012,6 +1026,7 @@ def test_bad_zip64_extra(self):
1012
1026
with self .assertRaises (zipfile .BadZipFile ) as e :
1013
1027
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1014
1028
self .assertIn ('header offset' , str (e .exception ).lower ())
1029
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1015
1030
1016
1031
# zip64 compress size present, zip64 header offset present, one field
1017
1032
# in extra, expecting two, equals missing header offset
@@ -1024,6 +1039,7 @@ def test_bad_zip64_extra(self):
1024
1039
with self .assertRaises (zipfile .BadZipFile ) as e :
1025
1040
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1026
1041
self .assertIn ('header offset' , str (e .exception ).lower ())
1042
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1027
1043
1028
1044
# zip64 file size present, zip64 header offset present, one field in
1029
1045
# extra, expecting two, equals missing header offset
@@ -1036,6 +1052,7 @@ def test_bad_zip64_extra(self):
1036
1052
with self .assertRaises (zipfile .BadZipFile ) as e :
1037
1053
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1038
1054
self .assertIn ('header offset' , str (e .exception ).lower ())
1055
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1039
1056
1040
1057
# zip64 header offset present, no fields in extra, expecting one,
1041
1058
# equals missing header offset
@@ -1047,6 +1064,63 @@ def test_bad_zip64_extra(self):
1047
1064
with self .assertRaises (zipfile .BadZipFile ) as e :
1048
1065
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1049
1066
self .assertIn ('header offset' , str (e .exception ).lower ())
1067
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1068
+
1069
+ def test_bad_zip64_end_of_central_dir (self ):
1070
+ zipdata = self .make_zip64_file (end_of_central_dir_size = 0 )
1071
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1072
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1073
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1074
+
1075
+ zipdata = self .make_zip64_file (end_of_central_dir_size = 100 )
1076
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1077
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1078
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1079
+
1080
+ zipdata = self .make_zip64_file (offset_to_end_of_central_dir = 0 )
1081
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1082
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1083
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1084
+
1085
+ zipdata = self .make_zip64_file (offset_to_end_of_central_dir = 1000 )
1086
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*locator' ):
1087
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1088
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1089
+
1090
+ def test_zip64_end_of_central_dir_record_not_found (self ):
1091
+ zipdata = self .make_zip64_file ()
1092
+ zipdata = zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1093
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1094
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1095
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1096
+
1097
+ zipdata = self .make_zip64_file (
1098
+ extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1099
+ zipdata = zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1100
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1101
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1102
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1103
+
1104
+ def test_zip64_extensible_data (self ):
1105
+ # These values are what is set in the make_zip64_file method.
1106
+ expected_file_size = 8
1107
+ expected_compress_size = 8
1108
+ expected_header_offset = 0
1109
+ expected_content = b"test1234"
1110
+
1111
+ zipdata = self .make_zip64_file (
1112
+ extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1113
+ with zipfile .ZipFile (io .BytesIO (zipdata )) as zf :
1114
+ zinfo = zf .infolist ()[0 ]
1115
+ self .assertEqual (zinfo .file_size , expected_file_size )
1116
+ self .assertEqual (zinfo .compress_size , expected_compress_size )
1117
+ self .assertEqual (zinfo .header_offset , expected_header_offset )
1118
+ self .assertEqual (zf .read (zinfo ), expected_content )
1119
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (zipdata )))
1120
+
1121
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1122
+ zipfile .ZipFile (io .BytesIO (b'prepended' + zipdata ))
1123
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (b'prepended' + zipdata )))
1050
1124
1051
1125
def test_generated_valid_zip64_extra (self ):
1052
1126
# These values are what is set in the make_zip64_file method.
0 commit comments