]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Issue 332: Be more careful guessing file mode information from
authorTim Kientzle <kientzle@acm.org>
Sun, 24 Nov 2013 16:44:34 +0000 (08:44 -0800)
committerTim Kientzle <kientzle@acm.org>
Sun, 24 Nov 2013 16:44:34 +0000 (08:44 -0800)
incomplete Zip archives.  In particular, some epub files have
0 in the file type part of the mode field.

Makefile.am
libarchive/archive_read_support_format_zip.c
libarchive/test/CMakeLists.txt
libarchive/test/test_read_format_zip_nofiletype.c [new file with mode: 0644]
libarchive/test/test_read_format_zip_nofiletype.zip.uu [new file with mode: 0644]

index 9521adf96c4049f22a3a64f7f1eb7b4cd2b1bbed..06f3355dd9d113610e1f7b4c6123923a8adfc8f9 100644 (file)
@@ -682,10 +682,14 @@ libarchive_test_EXTRA_DIST=\
        libarchive/test/test_read_format_zip_filename_cp932.zip.uu      \
        libarchive/test/test_read_format_zip_filename_koi8r.zip.uu      \
        libarchive/test/test_read_format_zip_filename_utf8_jp.zip.uu    \
-       libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu   \
        libarchive/test/test_read_format_zip_filename_utf8_ru.zip.uu    \
+       libarchive/test/test_read_format_zip_filename_utf8_ru2.zip.uu   \
        libarchive/test/test_read_format_zip_length_at_end.zip.uu       \
        libarchive/test/test_read_format_zip_mac_metadata.zip.uu        \
+       libarchive/test/test_read_format_zip_nofiletype.zip.uu          \
+       libarchive/test/test_read_format_zip_padded1.zip.uu             \
+       libarchive/test/test_read_format_zip_padded2.zip.uu             \
+       libarchive/test/test_read_format_zip_padded3.zip.uu             \
        libarchive/test/test_read_format_zip_sfx.uu                     \
        libarchive/test/test_read_format_zip_symlink.zip.uu             \
        libarchive/test/test_read_format_zip_ux.zip.uu                  \
index e6b9c76902dec8ad659f35b1213c4154a9490e86..a261b35d7bf4caabfce1e4b9207eaaf3f4e43dcf 100644 (file)
@@ -1071,24 +1071,29 @@ zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
        }
        zip_read_consume(a, filename_length);
 
-       if (zip_entry->mode == 0) {
+       if ((zip_entry->mode & AE_IFMT) == 0) {
                /* Especially in streaming mode, we can end up
-                  here without having seen any mode information.
+                  here without having seen proper mode information.
                   Guess from the filename. */
                wp = archive_entry_pathname_w(entry);
                if (wp != NULL) {
                        len = wcslen(wp);
                        if (len > 0 && wp[len - 1] == L'/')
-                               zip_entry->mode = AE_IFDIR | 0777;
+                               zip_entry->mode |= AE_IFDIR;
                        else
-                               zip_entry->mode = AE_IFREG | 0666;
+                               zip_entry->mode |= AE_IFREG;
                } else {
                        cp = archive_entry_pathname(entry);
                        len = (cp != NULL)?strlen(cp):0;
                        if (len > 0 && cp[len - 1] == '/')
-                               zip_entry->mode = AE_IFDIR | 0777;
+                               zip_entry->mode |= AE_IFDIR;
                        else
-                               zip_entry->mode = AE_IFREG | 0666;
+                               zip_entry->mode |= AE_IFREG;
+               }
+               if (zip_entry->mode == AE_IFDIR) {
+                       zip_entry->mode |= 0777;
+               } else if (zip_entry->mode == AE_IFREG) {
+                       zip_entry->mode |= 0666;
                }
        }
 
index 560e7ff4c99c6916ee256e4bbefbc64e25d4c750..55de0ca65fb1d41598fedd02b29e695595bee44e 100644 (file)
@@ -143,6 +143,7 @@ IF(ENABLE_TEST)
     test_read_format_zip_comment_stored.c
     test_read_format_zip_filename.c
     test_read_format_zip_mac_metadata.c
+    test_read_format_zip_nofiletype.c
     test_read_format_zip_padded.c
     test_read_format_zip_sfx.c
     test_read_large.c
diff --git a/libarchive/test/test_read_format_zip_nofiletype.c b/libarchive/test/test_read_format_zip_nofiletype.c
new file mode 100644 (file)
index 0000000..b01afab
--- /dev/null
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2013 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$");
+
+/*
+ * Issue 332:  Some epub files (which are really Zip archives) have
+ * nonsense in the "external file attributes" field.
+ */
+
+DEFINE_TEST(test_read_format_zip_nofiletype)
+{
+       const char *refname = "test_read_format_zip_nofiletype.zip";
+       char *p;
+       size_t s;
+       struct archive *a;
+       struct archive_entry *ae;
+       char data[16];
+
+       extract_reference_file(refname);
+       p = slurpfile(&s, refname);
+
+       assert((a = archive_read_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip_seekable(a));
+       assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("file1", archive_entry_pathname(ae));
+       assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae));
+       assertEqualInt(6, archive_entry_size(ae));
+       assertEqualIntA(a, 6, archive_read_data(a, data, 16));
+       assertEqualMem(data, "file1\x0a", 6);
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("dir2/", archive_entry_pathname(ae));
+       assertEqualInt(AE_IFDIR | 0755, archive_entry_mode(ae));
+       assertEqualInt(0, archive_entry_size(ae));
+       assertEqualIntA(a, 0, archive_read_data(a, data, 16));
+
+       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);
+}
diff --git a/libarchive/test/test_read_format_zip_nofiletype.zip.uu b/libarchive/test/test_read_format_zip_nofiletype.zip.uu
new file mode 100644 (file)
index 0000000..e05e9f0
--- /dev/null
@@ -0,0 +1,8 @@
+begin 644 test_read_format_zip_nofiletype.zip
+M4$L#!`H``````$-$>$,$]RGB!@````8````%````9FEL93%F:6QE,0I02P,$
+M"@``````141X0P````````````````4```!D:7(R+U!+`0(>`PH``````$-$
+M>$,$]RGB!@````8````%``````````$```"D`0````!F:6QE,5!+`0(>`PH`
+M`````$5$>$,````````````````%````````````$`#M`2D```!D:7(R+U!+
+4!08``````@`"`&8```!,````````
+`
+end