diff --git a/testdata/readme.mismatchednameszip b/testdata/readme.mismatchednameszip new file mode 100644 index 0000000..df6795a --- /dev/null +++ b/testdata/readme.mismatchednameszip @@ -0,0 +1,59 @@ +# Mismatched names between local file header and central directory + +The name of the file is recorded in both the local file header and the central +directory. These should be the same according to the specification and if these +are not the same, then the file is invalid (according to the specification), +but that's not how the tools behave. + +Let's take the regular test file `test.zip`: + +``` +$ unzip -l test.zip +Archive: test.zip +This is a zipfile comment. + Length Date Time Name +--------- ---------- ----- ---- + 26 09-05-2010 04:12 test.txt + 785 09-05-2010 07:52 gophercolor16x16.png +--------- ------- + 811 2 files +``` + +and change the name of the file `test.txt` in the local file header +`tets.txt` (for example using `ghex`) and then moved to a file called +`test-mismatched-names.zip`. + +The `unzip` program will report that there is a mismatch, but then proceeed +to use the name found in the central directory: + +``` + unzip test-mismatched-names.zip +Archive: test-mismatched-names.zip +This is a zipfile comment. +test.txt: mismatching "local" filename (tets.txt), + continuing with "central" filename version + inflating: test.txt + extracting: gophercolor16x16.png +``` + +`p7zip` will not report anything about a mismatch, but simply use the name +from the central directory. `zipinfo` will not report a mismatch but report +the name from the central directory. + +Python's `zipfile` will report an error: + +``` +>>> import zipfile +>>> test_zip = zipfile.ZipFile('test-mismatched-names.zip') +>>> test_zip.extractall() +Traceback (most recent call last): + File "", line 1, in + File "/usr/lib64/python3.12/zipfile/__init__.py", line 1744, in extractall + self._extract_member(zipinfo, path, pwd) + File "/usr/lib64/python3.12/zipfile/__init__.py", line 1800, in _extract_member + with self.open(member, pwd=pwd) as source, \ + ^^^^^^^^^^^^^^^^^^^^^^^^^^ + File "/usr/lib64/python3.12/zipfile/__init__.py", line 1646, in open + raise BadZipFile( +zipfile.BadZipFile: File name in directory 'test.txt' and header b'tets.txt' differ. +``` diff --git a/testdata/test-mismatched-names.zip b/testdata/test-mismatched-names.zip new file mode 100644 index 0000000..3a440ae Binary files /dev/null and b/testdata/test-mismatched-names.zip differ diff --git a/ziplinter/src/snapshots/ziplinter__test__test-mismatched-names.zip.snap b/ziplinter/src/snapshots/ziplinter__test__test-mismatched-names.zip.snap new file mode 100644 index 0000000..9e3d1e7 --- /dev/null +++ b/ziplinter/src/snapshots/ziplinter__test__test-mismatched-names.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": "Deflate", + "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": "tets.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 +}