@@ -898,6 +898,8 @@ def make_zip64_file(
898
898
self , file_size_64_set = False , file_size_extra = False ,
899
899
compress_size_64_set = False , compress_size_extra = False ,
900
900
header_offset_64_set = False , header_offset_extra = False ,
901
+ extensible_data = b'' ,
902
+ end_of_central_dir_size = None , offset_to_end_of_central_dir = None ,
901
903
):
902
904
"""Generate bytes sequence for a zip with (incomplete) zip64 data.
903
905
@@ -951,6 +953,12 @@ def make_zip64_file(
951
953
952
954
central_dir_size = struct .pack ('<Q' , 58 + 8 * len (central_zip64_fields ))
953
955
offset_to_central_dir = struct .pack ('<Q' , 50 + 8 * len (local_zip64_fields ))
956
+ if end_of_central_dir_size is None :
957
+ end_of_central_dir_size = 44 + len (extensible_data )
958
+ if offset_to_end_of_central_dir is None :
959
+ offset_to_end_of_central_dir = (108
960
+ + 8 * len (local_zip64_fields )
961
+ + 8 * len (central_zip64_fields ))
954
962
955
963
local_extra_length = struct .pack ("<H" , 4 + 8 * len (local_zip64_fields ))
956
964
central_extra_length = struct .pack ("<H" , 4 + 8 * len (central_zip64_fields ))
@@ -979,14 +987,17 @@ def make_zip64_file(
979
987
+ filename
980
988
+ central_extra
981
989
# Zip64 end of central directory
982
- + b"PK\x06 \x06 ,\x00 \x00 \x00 \x00 \x00 \x00 \x00 -\x00 -"
983
- + b"\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 "
990
+ + b"PK\x06 \x06 "
991
+ + struct .pack ('<Q' , end_of_central_dir_size )
992
+ + b"-\x00 -\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 "
984
993
+ b"\x00 \x00 \x01 \x00 \x00 \x00 \x00 \x00 \x00 \x00 "
985
994
+ central_dir_size
986
995
+ offset_to_central_dir
996
+ + extensible_data
987
997
# Zip64 end of central directory locator
988
- + b"PK\x06 \x07 \x00 \x00 \x00 \x00 l\x00 \x00 \x00 \x00 \x00 \x00 \x00 \x01 "
989
- + b"\x00 \x00 \x00 "
998
+ + b"PK\x06 \x07 \x00 \x00 \x00 \x00 "
999
+ + struct .pack ('<Q' , offset_to_end_of_central_dir )
1000
+ + b"\x01 \x00 \x00 \x00 "
990
1001
# end of central directory
991
1002
+ b"PK\x05 \x06 \x00 \x00 \x00 \x00 \x01 \x00 \x01 \x00 :\x00 \x00 \x00 2\x00 "
992
1003
+ b"\x00 \x00 \x00 \x00 "
@@ -1017,6 +1028,7 @@ def test_bad_zip64_extra(self):
1017
1028
with self .assertRaises (zipfile .BadZipFile ) as e :
1018
1029
zipfile .ZipFile (io .BytesIO (missing_file_size_extra ))
1019
1030
self .assertIn ('file size' , str (e .exception ).lower ())
1031
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_file_size_extra )))
1020
1032
1021
1033
# zip64 file size present, zip64 compress size present, one field in
1022
1034
# extra, expecting two, equals missing compress size.
@@ -1028,6 +1040,7 @@ def test_bad_zip64_extra(self):
1028
1040
with self .assertRaises (zipfile .BadZipFile ) as e :
1029
1041
zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
1030
1042
self .assertIn ('compress size' , str (e .exception ).lower ())
1043
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
1031
1044
1032
1045
# zip64 compress size present, no fields in extra, expecting one,
1033
1046
# equals missing compress size.
@@ -1037,6 +1050,7 @@ def test_bad_zip64_extra(self):
1037
1050
with self .assertRaises (zipfile .BadZipFile ) as e :
1038
1051
zipfile .ZipFile (io .BytesIO (missing_compress_size_extra ))
1039
1052
self .assertIn ('compress size' , str (e .exception ).lower ())
1053
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_compress_size_extra )))
1040
1054
1041
1055
# zip64 file size present, zip64 compress size present, zip64 header
1042
1056
# offset present, two fields in extra, expecting three, equals missing
@@ -1051,6 +1065,7 @@ def test_bad_zip64_extra(self):
1051
1065
with self .assertRaises (zipfile .BadZipFile ) as e :
1052
1066
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1053
1067
self .assertIn ('header offset' , str (e .exception ).lower ())
1068
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1054
1069
1055
1070
# zip64 compress size present, zip64 header offset present, one field
1056
1071
# in extra, expecting two, equals missing header offset
@@ -1063,6 +1078,7 @@ def test_bad_zip64_extra(self):
1063
1078
with self .assertRaises (zipfile .BadZipFile ) as e :
1064
1079
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1065
1080
self .assertIn ('header offset' , str (e .exception ).lower ())
1081
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1066
1082
1067
1083
# zip64 file size present, zip64 header offset present, one field in
1068
1084
# extra, expecting two, equals missing header offset
@@ -1075,6 +1091,7 @@ def test_bad_zip64_extra(self):
1075
1091
with self .assertRaises (zipfile .BadZipFile ) as e :
1076
1092
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1077
1093
self .assertIn ('header offset' , str (e .exception ).lower ())
1094
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1078
1095
1079
1096
# zip64 header offset present, no fields in extra, expecting one,
1080
1097
# equals missing header offset
@@ -1086,6 +1103,63 @@ def test_bad_zip64_extra(self):
1086
1103
with self .assertRaises (zipfile .BadZipFile ) as e :
1087
1104
zipfile .ZipFile (io .BytesIO (missing_header_offset_extra ))
1088
1105
self .assertIn ('header offset' , str (e .exception ).lower ())
1106
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (missing_header_offset_extra )))
1107
+
1108
+ def test_bad_zip64_end_of_central_dir (self ):
1109
+ zipdata = self .make_zip64_file (end_of_central_dir_size = 0 )
1110
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1111
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1112
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1113
+
1114
+ zipdata = self .make_zip64_file (end_of_central_dir_size = 100 )
1115
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1116
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1117
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1118
+
1119
+ zipdata = self .make_zip64_file (offset_to_end_of_central_dir = 0 )
1120
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*record' ):
1121
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1122
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1123
+
1124
+ zipdata = self .make_zip64_file (offset_to_end_of_central_dir = 1000 )
1125
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'Corrupt.*locator' ):
1126
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1127
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1128
+
1129
+ def test_zip64_end_of_central_dir_record_not_found (self ):
1130
+ zipdata = self .make_zip64_file ()
1131
+ zipdata = zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1132
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1133
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1134
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1135
+
1136
+ zipdata = self .make_zip64_file (
1137
+ extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1138
+ zipdata = zipdata .replace (b"PK\x06 \x06 " , b'\x00 ' * 4 )
1139
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1140
+ zipfile .ZipFile (io .BytesIO (zipdata ))
1141
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (zipdata )))
1142
+
1143
+ def test_zip64_extensible_data (self ):
1144
+ # These values are what is set in the make_zip64_file method.
1145
+ expected_file_size = 8
1146
+ expected_compress_size = 8
1147
+ expected_header_offset = 0
1148
+ expected_content = b"test1234"
1149
+
1150
+ zipdata = self .make_zip64_file (
1151
+ extensible_data = b'\xca \xfe \x04 \x00 \x00 \x00 data' )
1152
+ with zipfile .ZipFile (io .BytesIO (zipdata )) as zf :
1153
+ zinfo = zf .infolist ()[0 ]
1154
+ self .assertEqual (zinfo .file_size , expected_file_size )
1155
+ self .assertEqual (zinfo .compress_size , expected_compress_size )
1156
+ self .assertEqual (zinfo .header_offset , expected_header_offset )
1157
+ self .assertEqual (zf .read (zinfo ), expected_content )
1158
+ self .assertTrue (zipfile .is_zipfile (io .BytesIO (zipdata )))
1159
+
1160
+ with self .assertRaisesRegex (zipfile .BadZipFile , 'record not found' ):
1161
+ zipfile .ZipFile (io .BytesIO (b'prepended' + zipdata ))
1162
+ self .assertFalse (zipfile .is_zipfile (io .BytesIO (b'prepended' + zipdata )))
1089
1163
1090
1164
def test_generated_valid_zip64_extra (self ):
1091
1165
# These values are what is set in the make_zip64_file method.
0 commit comments