@@ -907,6 +907,146 @@ public static async Task ZipArchive_InvalidHuffmanData()
907907            } 
908908        } 
909909
910+         [ Fact ] 
911+         public  static void  ZipArchive_InvalidVersionToExtract ( ) 
912+         { 
913+             using  ( MemoryStream  updatedStream  =  new  MemoryStream ( ) ) 
914+             { 
915+                 int  originalLocalVersionToExtract  =  s_inconsistentVersionToExtract [ 4 ] ; 
916+                 int  originalCentralDirectoryVersionToExtract  =  s_inconsistentVersionToExtract [ 57 ] ; 
917+ 
918+                 // The existing archive will have a "version to extract" of 0.0, but will contain entries 
919+                 // with deflate compression (which has a minimum version to extract of 2.0.) 
920+                 Assert . Equal ( 0x00 ,  originalLocalVersionToExtract ) ; 
921+                 Assert . Equal ( 0x00 ,  originalCentralDirectoryVersionToExtract ) ; 
922+ 
923+                 // Write the example data to the stream. We expect to be able to read it (and the entry contents) successfully. 
924+                 updatedStream . Write ( s_inconsistentVersionToExtract ) ; 
925+                 updatedStream . Seek ( 0 ,  SeekOrigin . Begin ) ; 
926+ 
927+                 using  ( ZipArchive  originalArchive  =  new  ZipArchive ( updatedStream ,  ZipArchiveMode . Read ,  true ) ) 
928+                 { 
929+                     Assert . Equal ( 1 ,  originalArchive . Entries . Count ) ; 
930+ 
931+                     ZipArchiveEntry  firstEntry  =  originalArchive . Entries [ 0 ] ; 
932+ 
933+                     Assert . Equal ( "first.bin" ,  firstEntry . Name ) ; 
934+                     Assert . Equal ( 10 ,  firstEntry . Length ) ; 
935+ 
936+                     using  ( Stream  entryStream  =  firstEntry . Open ( ) ) 
937+                     { 
938+                         Assert . Equal ( 10 ,  firstEntry . Length ) ; 
939+ 
940+                         byte [ ]  uncompressedBytes  =  new  byte [ firstEntry . Length ] ; 
941+                         int  bytesRead  =  entryStream . Read ( uncompressedBytes ) ; 
942+ 
943+                         Assert . Equal ( 10 ,  bytesRead ) ; 
944+ 
945+                         Assert . Equal ( new  byte [ ]  {  0x00 ,  0x01 ,  0x02 ,  0x03 ,  0x04 ,  0x05 ,  0x06 ,  0x07 ,  0x08 ,  0x09  } ,  uncompressedBytes ) ; 
946+                     } 
947+                 } 
948+ 
949+                 updatedStream . Seek ( 0 ,  SeekOrigin . Begin ) ; 
950+ 
951+                 // Create a new entry, forcing the central directory headers to be rewritten. The local file header 
952+                 // for first.bin would normally be skipped (because it hasn't changed) but it needs to be rewritten 
953+                 // because the central directory headers will be rewritten with a valid value and the local file header 
954+                 // needs to match. 
955+                 using  ( ZipArchive  updatedArchive  =  new  ZipArchive ( updatedStream ,  ZipArchiveMode . Update ) ) 
956+                 { 
957+                     ZipArchiveEntry  newEntry  =  updatedArchive . CreateEntry ( "second.bin" ,  CompressionLevel . NoCompression ) ; 
958+                 } 
959+ 
960+                 byte [ ]  updatedContents  =  updatedStream . ToArray ( ) ; 
961+                 int  updatedLocalVersionToExtract  =  updatedContents [ 4 ] ; 
962+                 int  updatedCentralDirectoryVersionToExtract  =  updatedContents [ 97 ] ; 
963+ 
964+                 Assert . Equal ( 20 ,  updatedCentralDirectoryVersionToExtract ) ; 
965+                 Assert . Equal ( 20 ,  updatedLocalVersionToExtract ) ; 
966+             } 
967+         } 
968+ 
969+         private  static readonly  byte [ ]  s_inconsistentVersionToExtract  = 
970+         { 
971+             // ===== Local file header signature 0x04034b50 
972+             0x50 ,  0x4b ,  0x03 ,  0x04 , 
973+             // version to extract 0.0 (invalid - this should be at least 2.0 to make use of deflate compression) 
974+             0x00 ,  0x00 , 
975+             // general purpose flags 
976+             0x02 ,  0x00 ,    // 0000_0002 'for maximum-compression deflating' 
977+             // Deflate 
978+             0x08 ,  0x00 , 
979+             // Last mod file time 
980+             0x3b ,  0x33 , 
981+             // Last mod date 
982+             0x3f ,  0x5a , 
983+             // CRC32 
984+             0x46 ,  0xd7 ,  0x6c ,  0x45 , 
985+             // compressed size 
986+             0x0c ,  0x00 ,  0x00 ,  0x00 , 
987+             // uncompressed size 
988+             0x0a ,  0x00 ,  0x00 ,  0x00 , 
989+             // file name length 
990+             0x09 ,  0x00 , 
991+             // extra field length 
992+             0x00 ,  0x00 , 
993+             // filename 
994+             0x66 ,  0x69 ,  0x72 ,  0x73 ,  0x74 ,  0x2e ,  0x62 ,  0x69 ,  0x6e , 
995+             // ------------- 
996+             // Data! 
997+             0x63 ,  0x60 ,  0x64 ,  0x62 ,  0x66 ,  0x61 ,  0x65 ,  0x63 ,  0xe7 ,  0xe0 ,  0x04 ,  0x00 , 
998+             // -------- Central directory signature 0x02014b50 
999+             0x50 ,  0x4b ,  0x01 ,  0x02 , 
1000+             // version made by 2.0 
1001+             0x14 ,  0x00 , 
1002+             // version to extract 0.0 (invalid - this should be at least 2.0 to make use of deflate compression) 
1003+             0x00 ,  0x00 , 
1004+             // general purpose flags 
1005+             0x02 ,  0x00 , 
1006+             // Deflate 
1007+             0x08 ,  0x00 , 
1008+             // Last mod file time 
1009+             0x3b ,  0x33 , 
1010+             // Last mod date 
1011+             0x3f ,  0x5a , 
1012+             // CRC32 
1013+             0x46 ,  0xd7 ,  0x6c ,  0x45 , 
1014+             // compressed size 
1015+             0x0c ,  0x00 ,  0x00 ,  0x00 , 
1016+             // uncompressed size 
1017+             0x0a ,  0x00 ,  0x00 ,  0x00 , 
1018+             // file name length 
1019+             0x09 ,  0x00 , 
1020+             // extra field length 
1021+             0x00 ,  0x00 , 
1022+             // file comment length 
1023+             0x00 ,  0x00 , 
1024+             // disk number start 
1025+             0x00 ,  0x00 , 
1026+             // internal file attributes 
1027+             0x00 ,  0x00 , 
1028+             // external file attributes 
1029+             0x00 ,  0x00 ,  0x00 ,  0x00 , 
1030+             // relative offset of local header 
1031+             0x00 ,  0x00 ,  0x00 ,  0x00 , 
1032+             // file name 
1033+             0x66 ,  0x69 ,  0x72 ,  0x73 ,  0x74 ,  0x2e ,  0x62 ,  0x69 ,  0x6e , 
1034+             // == 'end of CD' signature 0x06054b50 
1035+             0x50 ,  0x4b ,  0x05 ,  0x06 , 
1036+             // disk number, disk number with CD 
1037+             0x00 ,  0x00 , 
1038+             0x00 ,  0x00 , 
1039+             // total number of entries in CD on this disk, and overall 
1040+             0x01 ,  0x00 , 
1041+             0x01 ,  0x00 , 
1042+             // size of CD 
1043+             0x37 ,  0x00 ,  0x00 ,  0x00 , 
1044+             // offset of start of CD wrt start disk 
1045+             0x33 ,  0x00 ,  0x00 ,  0x00 , 
1046+             // comment length 
1047+             0x00 ,  0x00 
1048+         } ; 
1049+ 
9101050        private  static readonly  byte [ ]  s_slightlyIncorrectZip64  = 
9111051        { 
9121052            // ===== Local file header signature 0x04034b50 
@@ -925,7 +1065,7 @@ public static async Task ZipArchive_InvalidHuffmanData()
9251065            0x0c ,  0x7e ,  0x7f ,  0xd8 , 
9261066            // compressed size 
9271067            0xff ,  0xff ,  0xff ,  0xff , 
928-             // UNcompressed  size 
1068+             // uncompressed  size 
9291069            0xff ,  0xff ,  0xff ,  0xff , 
9301070            // file name length 
9311071            0x08 ,  0x00 , 
@@ -976,7 +1116,7 @@ public static async Task ZipArchive_InvalidHuffmanData()
9761116            0x0c ,  0x7e ,  0x7f ,  0xd8 , 
9771117            // 4 byte compressed size, index 120 (-1 indicates refer to Zip64 extra field) 
9781118            0xff ,  0xff ,  0xff ,  0xff , 
979-             // 4 byte UNcompressed  size, index 124 (-1 indicates refer to Zip64 extra field) 
1119+             // 4 byte uncompressed  size, index 124 (-1 indicates refer to Zip64 extra field) 
9801120            0xff ,  0xff ,  0xff ,  0xff , 
9811121            // file name length 
9821122            0x08 ,  0x00 , 
@@ -1066,7 +1206,7 @@ public static async Task ZipArchive_InvalidHuffmanData()
10661206            0x0c ,  0x7e ,  0x7f ,  0xd8 , 
10671207            // compressed size 
10681208            0xff ,  0xff ,  0xff ,  0xff , 
1069-             // UNcompressed  size 
1209+             // uncompressed  size 
10701210            0xff ,  0xff ,  0xff ,  0xff , 
10711211            // file name length 
10721212
@@ -1079,7 +1219,7 @@ public static async Task ZipArchive_InvalidHuffmanData()
10791219            0x01 ,  0x00 , 
10801220            // size of extra field block 
10811221            0x20 ,  0x00 , 
1082-                     // 8 byte Zip64 UNcompressed  size, index 42 
1222+                     // 8 byte Zip64 uncompressed  size, index 42 
10831223                    0x04 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x00 , 
10841224                    // 8 byte Zip64 compressed size, index 50 
10851225                    0x06 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x00 ,  0x00 , 
@@ -1122,7 +1262,7 @@ public static async Task ZipArchive_InvalidHuffmanData()
11221262            0x0c ,  0x7e ,  0x7f ,  0xd8 , 
11231263            // 4 byte compressed size, index 120 (-1 indicates refer to Zip64 extra field) 
11241264            0xff ,  0xff ,  0xff ,  0xff , 
1125-             // 4 byte UNcompressed  size, index 124 (-1 indicates refer to Zip64 extra field) 
1265+             // 4 byte uncompressed  size, index 124 (-1 indicates refer to Zip64 extra field) 
11261266            0xff ,  0xff ,  0xff ,  0xff , 
11271267            // file name length 
11281268            0x08 ,  0x00 , 
0 commit comments