diff --git a/testdata/readme.mismatched_compression b/testdata/readme.mismatched_compression new file mode 100644 index 0000000..f5389e7 --- /dev/null +++ b/testdata/readme.mismatched_compression @@ -0,0 +1,120 @@ +# Mismatched compression in local file header and central directory + +When processing entries in a ZIP file it is assumed that the local file header +and the central directory match, which does not need to be the case. One field +that is in both is the `compression method`. If these do not match, then the +different programs don't behave in the same way. + +The two files `test_mismatched_compression_central.zip` and +`test_mismatched_compression_local.zip` are modified versions of `test.zip` and +both contain a file (compressed with "deflate") where the compression method in +the header has been changed to "bzip". The first file has the wrong value in +the central directory, the other in the the local file header. + +Extracting these with different programs reveals some interesting behaviour: + +``` +$ unzip test_mismatched_compression_central.zip +Archive: test_mismatched_compression_central.zip +This is a zipfile comment. + inflating: test.txt + extracting: gophercolor16x16.png +``` +The files are correctly extracted, and the exit code of the program is `0` +(success): + +``` +$ echo $? +0 +``` + +This means that `unzip` ignores the `compression method` field in the central +directory and only looks at the local file header. + +When unpacking the one with the value changed in the local file header `unzip` +is not successful: + +``` +$ unzip test_mismatched_compression_local.zip +Archive: test_mismatched_compression_local.zip +This is a zipfile comment. + bunzipping: test.txt +``` + +and the process ends there. Only a 0 byte file `test.txt` is extracted and the +exit code is `6`, meaning there was an error: + +``` +$ echo $? +6 +``` + +`p7zip` has similar behaviour, although it reports an error in both cases. + +``` +$ 7z x test_mismatched_compression_central.zip + +7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 +p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-6770HQ CPU @ 2.60GHz (506E3),ASM,AES-NI) + +Scanning the drive for archives: +1 file, 1170 bytes (2 KiB) + +Extracting archive: test_mismatched_compression_central.zip + +ERRORS: +Headers Error + +-- +Path = test_mismatched_compression_central.zip +Type = zip +ERRORS: +Headers Error +Physical Size = 1170 +Comment = This is a zipfile comment. + + + +Archives with Errors: 1 + +Open Errors: 1 +``` + +When the error is in the central directory the file `test.txt` is successfully +unpacked. + +``` +$ 7z x test_mismatched_compression_local.zip + +7-Zip [64] 16.02 : Copyright (c) 1999-2016 Igor Pavlov : 2016-05-21 +p7zip Version 16.02 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,8 CPUs Intel(R) Core(TM) i7-6770HQ CPU @ 2.60GHz (506E3),ASM,AES-NI) + +Scanning the drive for archives: +1 file, 1170 bytes (2 KiB) + +Extracting archive: test_mismatched_compression_local.zip + +ERRORS: +Headers Error + +-- +Path = test_mismatched_compression_local.zip +Type = zip +ERRORS: +Headers Error +Physical Size = 1170 +Comment = This is a zipfile comment. + +ERROR: Data Error : test.txt + +Sub items Errors: 1 + +Archives with Errors: 1 + +Open Errors: 1 + +Sub items Errors: 1 +``` + +When the error is in the local file header the file `test.txt` is not unpacked +and instead a 0 byte file is created. diff --git a/testdata/test_mismatched_compression_central.zip b/testdata/test_mismatched_compression_central.zip new file mode 100644 index 0000000..33b46eb Binary files /dev/null and b/testdata/test_mismatched_compression_central.zip differ diff --git a/testdata/test_mismatched_compression_local.zip b/testdata/test_mismatched_compression_local.zip new file mode 100644 index 0000000..7e95046 Binary files /dev/null and b/testdata/test_mismatched_compression_local.zip differ diff --git a/ziplinter/src/snapshots/ziplinter__test__test_mismatched_compression_central.zip.snap b/ziplinter/src/snapshots/ziplinter__test__test_mismatched_compression_central.zip.snap new file mode 100644 index 0000000..e9c0b28 --- /dev/null +++ b/ziplinter/src/snapshots/ziplinter__test__test_mismatched_compression_central.zip.snap @@ -0,0 +1,271 @@ +--- +source: ziplinter/src/lib.rs +expression: result +--- +{ + "comment": "This is a zipfile comment.", + "contents": [ + { + "central": { + "comment": "", + "compressed_size": 25, + "crc32": 3287144384, + "creator_version": { + "host_system": "Unix", + "version": 30 + }, + "disk_nbr_start": 0, + "external_attrs": 2175008768, + "extra": [ + 85, + 84, + 5, + 0, + 3, + 113, + 252, + 130, + 76, + 117, + 120, + 11, + 0, + 1, + 4, + 245, + 1, + 0, + 0, + 4, + 20, + 0, + 0, + 0 + ], + "flags": 0, + "header_offset": 0, + "internal_attrs": 1, + "method": "Bzip2", + "mode": 420, + "modified": "2010-09-05T02:12:01Z", + "name": "test.txt", + "reader_version": { + "host_system": "MsDos", + "version": 20 + }, + "uncompressed_size": 26 + }, + "local": { + "accessed": null, + "compressed_size": 25, + "crc32": 3287144384, + "created": null, + "extra": [ + 85, + 84, + 9, + 0, + 3, + 113, + 252, + 130, + 76, + 118, + 252, + 130, + 76, + 117, + 120, + 11, + 0, + 1, + 4, + 245, + 1, + 0, + 0, + 4, + 20, + 0, + 0, + 0 + ], + "flags": 0, + "gid": 501, + "header_offset": 0, + "method": "Deflate", + "method_specific": "None", + "mode": 0, + "modified": "2010-09-05T02:12:01Z", + "name": "test.txt", + "reader_version": { + "host_system": "MsDos", + "version": 20 + }, + "uid": 501, + "uncompressed_size": 26 + } + }, + { + "central": { + "comment": "", + "compressed_size": 785, + "crc32": 1423258110, + "creator_version": { + "host_system": "Unix", + "version": 30 + }, + "disk_nbr_start": 0, + "external_attrs": 2175008768, + "extra": [ + 85, + 84, + 5, + 0, + 3, + 58, + 48, + 131, + 76, + 117, + 120, + 11, + 0, + 1, + 4, + 245, + 1, + 0, + 0, + 4, + 20, + 0, + 0, + 0 + ], + "flags": 0, + "header_offset": 91, + "internal_attrs": 0, + "method": "Store", + "mode": 420, + "modified": "2010-09-05T05:52:58Z", + "name": "gophercolor16x16.png", + "reader_version": { + "host_system": "MsDos", + "version": 10 + }, + "uncompressed_size": 785 + }, + "local": { + "accessed": null, + "compressed_size": 785, + "crc32": 1423258110, + "created": null, + "extra": [ + 85, + 84, + 9, + 0, + 3, + 58, + 48, + 131, + 76, + 59, + 48, + 131, + 76, + 117, + 120, + 11, + 0, + 1, + 4, + 245, + 1, + 0, + 0, + 4, + 20, + 0, + 0, + 0 + ], + "flags": 0, + "gid": 501, + "header_offset": 0, + "method": "Store", + "method_specific": "None", + "mode": 0, + "modified": "2010-09-05T05:52:58Z", + "name": "gophercolor16x16.png", + "reader_version": { + "host_system": "MsDos", + "version": 10 + }, + "uid": 501, + "uncompressed_size": 785 + } + } + ], + "encoding": "Utf8", + "eocd": { + "dir": { + "inner": { + "dir_disk_nbr": 0, + "dir_records_this_disk": 2, + "directory_offset": 954, + "directory_records": 2, + "directory_size": 168, + "disk_nbr": 0 + }, + "offset": 1122 + }, + "dir64": null, + "global_offset": 0 + }, + "parsed_ranges": [ + { + "contains": "end of central directory record", + "end": 1170, + "start": 1122 + }, + { + "contains": "central directory header", + "end": 1032, + "filename": "test.txt", + "start": 954 + }, + { + "contains": "central directory header", + "end": 1122, + "filename": "gophercolor16x16.png", + "start": 1032 + }, + { + "contains": "local file header", + "end": 66, + "filename": "test.txt", + "start": 0 + }, + { + "contains": "file data", + "end": 91, + "filename": "test.txt", + "start": 66 + }, + { + "contains": "local file header", + "end": 169, + "filename": "gophercolor16x16.png", + "start": 91 + }, + { + "contains": "file data", + "end": 954, + "filename": "gophercolor16x16.png", + "start": 169 + } + ], + "size": 1170 +} diff --git a/ziplinter/src/snapshots/ziplinter__test__test_mismatched_compression_local.zip.snap b/ziplinter/src/snapshots/ziplinter__test__test_mismatched_compression_local.zip.snap new file mode 100644 index 0000000..9a63842 --- /dev/null +++ b/ziplinter/src/snapshots/ziplinter__test__test_mismatched_compression_local.zip.snap @@ -0,0 +1,218 @@ +--- +source: ziplinter/src/lib.rs +expression: result +--- +{ + "comment": "This is a zipfile comment.", + "contents": [ + { + "central": { + "comment": "", + "compressed_size": 25, + "crc32": 3287144384, + "creator_version": { + "host_system": "Unix", + "version": 30 + }, + "disk_nbr_start": 0, + "external_attrs": 2175008768, + "extra": [ + 85, + 84, + 5, + 0, + 3, + 113, + 252, + 130, + 76, + 117, + 120, + 11, + 0, + 1, + 4, + 245, + 1, + 0, + 0, + 4, + 20, + 0, + 0, + 0 + ], + "flags": 0, + "header_offset": 0, + "internal_attrs": 1, + "method": "Deflate", + "mode": 420, + "modified": "2010-09-05T02:12:01Z", + "name": "test.txt", + "reader_version": { + "host_system": "MsDos", + "version": 20 + }, + "uncompressed_size": 26 + }, + "local": { + "error": "Custom { kind: Other, error: Decompression { method: Bzip2, msg: \"bzip2: bz2 header missing\" } }" + } + }, + { + "central": { + "comment": "", + "compressed_size": 785, + "crc32": 1423258110, + "creator_version": { + "host_system": "Unix", + "version": 30 + }, + "disk_nbr_start": 0, + "external_attrs": 2175008768, + "extra": [ + 85, + 84, + 5, + 0, + 3, + 58, + 48, + 131, + 76, + 117, + 120, + 11, + 0, + 1, + 4, + 245, + 1, + 0, + 0, + 4, + 20, + 0, + 0, + 0 + ], + "flags": 0, + "header_offset": 91, + "internal_attrs": 0, + "method": "Store", + "mode": 420, + "modified": "2010-09-05T05:52:58Z", + "name": "gophercolor16x16.png", + "reader_version": { + "host_system": "MsDos", + "version": 10 + }, + "uncompressed_size": 785 + }, + "local": { + "accessed": null, + "compressed_size": 785, + "crc32": 1423258110, + "created": null, + "extra": [ + 85, + 84, + 9, + 0, + 3, + 58, + 48, + 131, + 76, + 59, + 48, + 131, + 76, + 117, + 120, + 11, + 0, + 1, + 4, + 245, + 1, + 0, + 0, + 4, + 20, + 0, + 0, + 0 + ], + "flags": 0, + "gid": 501, + "header_offset": 0, + "method": "Store", + "method_specific": "None", + "mode": 0, + "modified": "2010-09-05T05:52:58Z", + "name": "gophercolor16x16.png", + "reader_version": { + "host_system": "MsDos", + "version": 10 + }, + "uid": 501, + "uncompressed_size": 785 + } + } + ], + "encoding": "Utf8", + "eocd": { + "dir": { + "inner": { + "dir_disk_nbr": 0, + "dir_records_this_disk": 2, + "directory_offset": 954, + "directory_records": 2, + "directory_size": 168, + "disk_nbr": 0 + }, + "offset": 1122 + }, + "dir64": null, + "global_offset": 0 + }, + "parsed_ranges": [ + { + "contains": "end of central directory record", + "end": 1170, + "start": 1122 + }, + { + "contains": "central directory header", + "end": 1032, + "filename": "test.txt", + "start": 954 + }, + { + "contains": "central directory header", + "end": 1122, + "filename": "gophercolor16x16.png", + "start": 1032 + }, + { + "contains": "local file header", + "end": 66, + "filename": "test.txt", + "start": 0 + }, + { + "contains": "local file header", + "end": 169, + "filename": "gophercolor16x16.png", + "start": 91 + }, + { + "contains": "file data", + "end": 954, + "filename": "gophercolor16x16.png", + "start": 169 + } + ], + "size": 1170 +}