@@ -887,6 +887,8 @@ def make_zip64_file(
887
887
self , file_size_64_set = False , file_size_extra = False ,
888
888
compress_size_64_set = False , compress_size_extra = False ,
889
889
header_offset_64_set = False , header_offset_extra = False ,
890
+ extensible_data = b'' ,
891
+ end_of_central_dir_size = None , offset_to_end_of_central_dir = None ,
890
892
):
891
893
"""Generate bytes sequence for a zip with (incomplete) zip64 data.
892
894
@@ -940,6 +942,12 @@ def make_zip64_file(
940
942
941
943
central_dir_size = struct .pack ('<Q' , 58 + 8 * len (central_zip64_fields ))
942
944
offset_to_central_dir = struct .pack ('<Q' , 50 + 8 * len (local_zip64_fields ))
945
+ if end_of_central_dir_size is None :
946
+ end_of_central_dir_size = 44 + len (extensible_data )
947
+ if offset_to_end_of_central_dir is None :
948
+ offset_to_end_of_central_dir = (108
949
+ + 8 * len (local_zip64_fields )
950
+ + 8 * len (central_zip64_fields ))
943
951
944
952
local_extra_length = struct .pack ("<H" , 4 + 8 * len (local_zip64_fields ))
945
953
central_extra_length = struct .pack ("<H" , 4 + 8 * len (central_zip64_fields ))
@@ -968,14 +976,17 @@ def make_zip64_file(
968
976
+ filename
969
977
+ central_extra
970
978
# Zip64 end of central directory
971
- + b"PK\x06 \x06 ,\x00 \x00 \x00 \x00 \x00 \x00 \x00 -\x00 -"
972
- + b"\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 "
979
+ + b"PK\x06 \x06 "
980
+ + struct .pack ('<Q' , end_of_central_dir_size )
981
+ + b"-\x00 -\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 "
973
982
+ b"\x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 \x00 \x00 "
974
983
+ central_dir_size
975
984
+ offset_to_central_dir
985
+ + extensible_data
976
986
# Zip64 end of central directory locator
977
- + b"PK\x06 \x07 \x00 \x00 \x00 \x00 l\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 "
978
- + b"\x00 \x00 \x00 "
987
+ + b"PK\x06 \x07 \x00 \x00 \x00 \x00 "
988
+ + struct .pack ('<Q' , offset_to_end_of_central_dir )
989
+ + b"\x01 \x00 \x00 \x00 "
979
990
# end of central directory
980
991
+ b"PK\x05 \x06 \x00 \x00 \x00 \x00 \x01 \x00 \x01 \x00 :\x00 \x00 \x00 2\x00 "
981
992
+ b"\x00 \x00 \x00 \x00 "
@@ -1006,6 +1017,7 @@ def test_bad_zip64_extra(self):
1006
1017
with self .assertRaises (zipfile .BadZipFile ) as e :
1007
1018
zipfile .ZipFile (io .BytesIO (missing_file_size_extra ))
1008
1019
self .assertIn ('file size' , str (e .exception ).lower ())
1020
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_file_size_extra )))
1009
1021
1010
1022
# zip64 file size present, zip64 compress size present, one field in
1011
1023
# extra, expecting two, equals missing compress size.
@@ -1017,6 +1029,7 @@ def test_bad_zip64_extra(self):
1017
1029
with self .assertRaises (zipfile .BadZipFile ) as e :
1018
1030
zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
1019
1031
self .assertIn ('compress size' , str (e .exception ).lower ())
1032
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
1020
1033
1021
1034
# zip64 compress size present, no fields in extra, expecting one,
1022
1035
# equals missing compress size.
@@ -1026,6 +1039,7 @@ def test_bad_zip64_extra(self):
1026
1039
with self .assertRaises (zipfile .BadZipFile ) as e :
1027
1040
zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
1028
1041
self .assertIn ('compress size' , str (e .exception ).lower ())
1042
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
1029
1043
1030
1044
# zip64 file size present, zip64 compress size present, zip64 header
1031
1045
# offset present, two fields in extra, expecting three, equals missing
@@ -1040,6 +1054,7 @@ def test_bad_zip64_extra(self):
1040
1054
with self .assertRaises (zipfile .BadZipFile ) as e :
1041
1055
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1042
1056
self .assertIn ('header offset' , str (e .exception ).lower ())
1057
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1043
1058
1044
1059
# zip64 compress size present, zip64 header offset present, one field
1045
1060
# in extra, expecting two, equals missing header offset
@@ -1052,6 +1067,7 @@ def test_bad_zip64_extra(self):
1052
1067
with self .assertRaises (zipfile .BadZipFile ) as e :
1053
1068
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1054
1069
self .assertIn ('header offset' , str (e .exception ).lower ())
1070
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1055
1071
1056
1072
# zip64 file size present, zip64 header offset present, one field in
1057
1073
# extra, expecting two, equals missing header offset
@@ -1064,6 +1080,7 @@ def test_bad_zip64_extra(self):
1064
1080
with self .assertRaises (zipfile .BadZipFile ) as e :
1065
1081
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1066
1082
self .assertIn ('header offset' , str (e .exception ).lower ())
1083
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1067
1084
1068
1085
# zip64 header offset present, no fields in extra, expecting one,
1069
1086
# equals missing header offset
@@ -1075,6 +1092,63 @@ def test_bad_zip64_extra(self):
1075
1092
with self .assertRaises (zipfile .BadZipFile ) as e :
1076
1093
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1077
1094
self .assertIn ('header offset' , str (e .exception ).lower ())
1095
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1096
+
1097
+ def test_bad_zip64_end_of_central_dir (self ):
1098
+ zipdata = self .make_zip64_file (end_of_central_dir_size = 0 )
1099
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1100
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1101
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1102
+
1103
+ zipdata = self .make_zip64_file (end_of_central_dir_size = 100 )
1104
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1105
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1106
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1107
+
1108
+ zipdata = self .make_zip64_file (offset_to_end_of_central_dir = 0 )
1109
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1110
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1111
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1112
+
1113
+ zipdata = self .make_zip64_file (offset_to_end_of_central_dir = 1000 )
1114
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*locator' ):
1115
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1116
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1117
+
1118
+ def test_zip64_end_of_central_dir_record_not_found (self ):
1119
+ zipdata = self .make_zip64_file ()
1120
+ zipdata = zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1121
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1122
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1123
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1124
+
1125
+ zipdata = self .make_zip64_file (
1126
+ extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1127
+ zipdata = zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1128
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1129
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1130
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1131
+
1132
+ def test_zip64_extensible_data (self ):
1133
+ # These values are what is set in the make_zip64_file method.
1134
+ expected_file_size = 8
1135
+ expected_compress_size = 8
1136
+ expected_header_offset = 0
1137
+ expected_content = b"test1234"
1138
+
1139
+ zipdata = self .make_zip64_file (
1140
+ extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1141
+ with zipfile .ZipFile (io .BytesIO (zipdata )) as zf :
1142
+ zinfo = zf .infolist ()[0 ]
1143
+ self .assertEqual (zinfo .file_size , expected_file_size )
1144
+ self .assertEqual (zinfo .compress_size , expected_compress_size )
1145
+ self .assertEqual (zinfo .header_offset , expected_header_offset )
1146
+ self .assertEqual (zf .read (zinfo ), expected_content )
1147
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (zipdata )))
1148
+
1149
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1150
+ zipfile .ZipFile (io .BytesIO (b'prepended' + zipdata ))
1151
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (b'prepended' + zipdata )))
1078
1152
1079
1153
def test_generated_valid_zip64_extra (self ):
1080
1154
# These values are what is set in the make_zip64_file method.
0 commit comments