| /*- |
| * Copyright (c) 2003-2007 Tim Kientzle |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR |
| * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
| * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, |
| * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
| * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| #include "test.h" |
| __FBSDID("$FreeBSD: head/lib/libarchive/test/test_compat_zip.c 196962 2009-09-08 05:02:41Z kientzle $"); |
| |
| /* Copy this function for each test file and adjust it accordingly. */ |
| DEFINE_TEST(test_compat_zip_1) |
| { |
| char name[] = "test_compat_zip_1.zip"; |
| struct archive_entry *ae; |
| struct archive *a; |
| int r; |
| |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); |
| extract_reference_file(name); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); |
| |
| /* Read first entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("META-INF/MANIFEST.MF", archive_entry_pathname(ae)); |
| |
| /* Read second entry. */ |
| r = archive_read_next_header(a, &ae); |
| if (r == ARCHIVE_FATAL && archive_zlib_version() == NULL) { |
| skipping("Skipping ZIP compression check: %s", |
| archive_error_string(a)); |
| goto finish; |
| } |
| assertEqualIntA(a, ARCHIVE_OK, r); |
| assertEqualString("tmp.class", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); |
| |
| assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); |
| assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP); |
| |
| finish: |
| assertEqualInt(ARCHIVE_OK, archive_read_close(a)); |
| assertEqualInt(ARCHIVE_OK, archive_read_free(a)); |
| } |
| |
| /* |
| * Verify that we skip junk between entries. The compat_zip_2.zip file |
| * has several bytes of junk between 'file1' and 'file2'. Such |
| * junk is routinely introduced by some Zip writers when they manipulate |
| * existing zip archives. |
| */ |
| DEFINE_TEST(test_compat_zip_2) |
| { |
| char name[] = "test_compat_zip_2.zip"; |
| struct archive_entry *ae; |
| struct archive *a; |
| |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); |
| extract_reference_file(name); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); |
| |
| /* Read first entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("file1", archive_entry_pathname(ae)); |
| |
| /* Read first entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("file2", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); |
| assertEqualInt(ARCHIVE_OK, archive_read_close(a)); |
| assertEqualInt(ARCHIVE_OK, archive_read_free(a)); |
| } |
| |
| /* |
| * Issue 185: Test a regression that got in between 2.6 and 2.7 that |
| * broke extraction of Zip entries with length-at-end. |
| */ |
| DEFINE_TEST(test_compat_zip_3) |
| { |
| const char *refname = "test_compat_zip_3.zip"; |
| struct archive_entry *ae; |
| struct archive *a; |
| |
| extract_reference_file(refname); |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); |
| |
| /* First entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("soapui-4.0.0/", archive_entry_pathname(ae)); |
| assertEqualInt(0, archive_entry_size(ae)); |
| assert(archive_entry_size_is_set(ae)); |
| assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); |
| |
| /* Second entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("soapui-4.0.0/soapui-settings.xml", archive_entry_pathname(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(1030, archive_entry_size(ae)); |
| assert(archive_entry_size_is_set(ae)); |
| |
| /* Extract under a different name. */ |
| archive_entry_set_pathname(ae, "test_3.txt"); |
| if(archive_zlib_version() != NULL) { |
| char *p; |
| size_t s; |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_extract(a, ae, 0)); |
| /* Verify the first 12 bytes actually got written to disk correctly. */ |
| p = slurpfile(&s, "test_3.txt"); |
| assertEqualInt(s, 1030); |
| assertEqualMem(p, "<?xml versio", 12); |
| free(p); |
| } else { |
| skipping("Skipping ZIP compression check, no libz support"); |
| } |
| assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| } |
| |
| /** |
| * A file with leading garbage (similar to an SFX file). |
| */ |
| DEFINE_TEST(test_compat_zip_4) |
| { |
| const char *refname = "test_compat_zip_4.zip"; |
| struct archive_entry *ae; |
| struct archive *a; |
| void *p; |
| size_t s; |
| |
| extract_reference_file(refname); |
| p = slurpfile(&s, refname); |
| |
| /* SFX files require seek support. */ |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 18)); |
| |
| /* First entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("foo", archive_entry_pathname(ae)); |
| assertEqualInt(4, archive_entry_size(ae)); |
| assert(archive_entry_size_is_set(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(0412, archive_entry_perm(ae)); |
| |
| /* Second entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("bar", archive_entry_pathname(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(4, archive_entry_size(ae)); |
| assert(archive_entry_size_is_set(ae)); |
| assertEqualInt(0567, archive_entry_perm(ae)); |
| |
| /* Third entry. */ |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("baz", archive_entry_pathname(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(4, archive_entry_size(ae)); |
| assert(archive_entry_size_is_set(ae)); |
| assertEqualInt(0644, archive_entry_perm(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| |
| /* Try reading without seek support and watch it fail. */ |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
| assertEqualIntA(a, ARCHIVE_FATAL, read_open_memory(a, p, s, 3)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| free(p); |
| } |
| /** |
| * Issue 152: A file generated by a tool that doesn't really |
| * believe in populating local file headers at all. This |
| * is only readable with the seeking reader. |
| */ |
| DEFINE_TEST(test_compat_zip_5) |
| { |
| const char *refname = "test_compat_zip_5.zip"; |
| struct archive_entry *ae; |
| struct archive *a; |
| void *p; |
| size_t s; |
| |
| extract_reference_file(refname); |
| p = slurpfile(&s, refname); |
| |
| /* Verify with seek support. |
| * Everything works correctly here. */ |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 18)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae)); |
| assertEqualInt(3559, archive_entry_size(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(0664, archive_entry_perm(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae)); |
| assertEqualInt(456, archive_entry_size(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(0664, archive_entry_perm(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae)); |
| assertEqualInt(1495, archive_entry_size(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(0664, archive_entry_perm(ae)); |
| /* TODO: Read some of the file data and verify it. |
| The code to read uncompressed Zip entries with "file at end" semantics |
| is tricky and should be verified more carefully. */ |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("_rels/.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("[Content_Types].xml", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| |
| /* Try reading without seek support. */ |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 3)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae)); |
| assertEqualInt(0, archive_entry_size(ae)); |
| assert(!archive_entry_size_is_set(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(0664, archive_entry_perm(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae)); |
| assertEqualInt(0, archive_entry_size(ae)); |
| assert(!archive_entry_size_is_set(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(0664, archive_entry_perm(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae)); |
| assertEqualInt(0, archive_entry_size(ae)); |
| assert(!archive_entry_size_is_set(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| assertEqualInt(0664, archive_entry_perm(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("_rels/.rels", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("[Content_Types].xml", archive_entry_pathname(ae)); |
| |
| assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| free(p); |
| } |
| |
| /* |
| * Issue 225: Errors extracting MSDOS Zip archives with directories. |
| */ |
| static void |
| compat_zip_6_verify(struct archive *a) |
| { |
| struct archive_entry *ae; |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("New Folder/New Folder/", archive_entry_pathname(ae)); |
| assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); |
| /* Zip timestamps are local time, so vary by time zone. */ |
| /* TODO: A more complex assert would work here; we could |
| verify that it's within +/- 24 hours of a particular value. */ |
| /* assertEqualInt(1327314468, archive_entry_mtime(ae)); */ |
| assertEqualInt(0, archive_entry_size(ae)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualString("New Folder/New Folder/New Text Document.txt", archive_entry_pathname(ae)); |
| assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); |
| /* Zip timestamps are local time, so vary by time zone. */ |
| /* assertEqualInt(1327314476, archive_entry_mtime(ae)); */ |
| assertEqualInt(11, archive_entry_size(ae)); |
| assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); |
| } |
| |
| DEFINE_TEST(test_compat_zip_6) |
| { |
| const char *refname = "test_compat_zip_6.zip"; |
| struct archive *a; |
| void *p; |
| size_t s; |
| |
| extract_reference_file(refname); |
| p = slurpfile(&s, refname); |
| |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 7)); |
| compat_zip_6_verify(a); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); |
| assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 7)); |
| compat_zip_6_verify(a); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| free(p); |
| } |
| |
| /* |
| * Issue 226: Try to reproduce hang when reading archives where the |
| * length-at-end marker ends exactly on a block boundary. |
| */ |
| DEFINE_TEST(test_compat_zip_7) |
| { |
| const char *refname = "test_compat_zip_7.xps"; |
| struct archive *a; |
| struct archive_entry *ae; |
| void *p; |
| size_t s; |
| int i; |
| |
| extract_reference_file(refname); |
| p = slurpfile(&s, refname); |
| |
| for (i = 1; i < 1000; ++i) { |
| assert((a = archive_read_new()) != NULL); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); |
| assertEqualIntA(a, ARCHIVE_OK, read_open_memory_minimal(a, p, s, i)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); |
| |
| assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); |
| } |
| free(p); |
| } |