]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Fix issue 257. Revise zip header offsets for reading SFX.
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Mon, 3 Dec 2012 05:59:18 +0000 (14:59 +0900)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Mon, 3 Dec 2012 05:59:18 +0000 (14:59 +0900)
Makefile.am
libarchive/archive_read_support_format_zip.c
libarchive/test/CMakeLists.txt
libarchive/test/test_read_format_zip_sfx.c [new file with mode: 0644]
libarchive/test/test_read_format_zip_sfx.uu [new file with mode: 0644]

index 1c7c8cbef687544f0c05fbefdaec5bff9faa79e3..c395bb2793e0b93ab99c2f7a7c1acc8efa34d85c 100644 (file)
@@ -405,6 +405,7 @@ libarchive_test_SOURCES=                                    \
        libarchive/test/test_read_format_zip_comment_stored.c   \
        libarchive/test/test_read_format_zip_filename.c         \
        libarchive/test/test_read_format_zip_mac_metadata.c     \
+       libarchive/test/test_read_format_zip_sfx.c              \
        libarchive/test/test_read_large.c                       \
        libarchive/test/test_read_pax_truncated.c               \
        libarchive/test/test_read_position.c                    \
@@ -647,6 +648,7 @@ libarchive_test_EXTRA_DIST=\
        libarchive/test/test_read_format_zip_filename_utf8_ru.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_sfx.uu                     \
        libarchive/test/test_read_format_zip_symlink.zip.uu             \
        libarchive/test/test_read_format_zip_ux.zip.uu                  \
        libarchive/test/test_read_large_splitted_rar_aa.uu              \
index 362621f3894e201f3492c40d794a9a152569def7..fd06b0bed29a711c00f76483ae66290ad3746112 100644 (file)
@@ -70,6 +70,7 @@ struct zip_entry {
 
 struct zip {
        /* Structural information about the archive. */
+       int64_t                 end_of_central_directory_offset;
        int64_t                 central_directory_offset;
        size_t                  central_directory_size;
        size_t                  central_directory_entries;
@@ -312,6 +313,7 @@ archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
        zip->central_directory_entries = archive_le16dec(p + 10);
        zip->central_directory_size = archive_le32dec(p + 12);
        zip->central_directory_offset = archive_le32dec(p + 16);
+       zip->end_of_central_directory_offset = filesize;
 
        /* Just one volume, so central dir must all be on this volume. */
        if (zip->central_directory_entries != archive_le16dec(p + 8))
@@ -408,6 +410,7 @@ static int
 slurp_central_directory(struct archive_read *a, struct zip *zip)
 {
        unsigned i;
+       int64_t correction;
        static const struct archive_rb_tree_ops rb_ops = {
                &cmp_node, &cmp_key
        };
@@ -415,6 +418,17 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
                &rsrc_cmp_node, &rsrc_cmp_key
        };
 
+       /*
+        * Consider the archive file we are reading may be SFX.
+        * So we have to calculate a SFX header size to revise
+        * ZIP header offsets.
+        */
+       correction = zip->end_of_central_directory_offset -
+           (zip->central_directory_offset + zip->central_directory_size);
+       /* The central directory offset is relative value, and so
+        * we revise this offset for SFX. */
+       zip->central_directory_offset += correction;
+
        __archive_read_seek(a, zip->central_directory_offset, SEEK_SET);
        zip->offset = zip->central_directory_offset;
        __archive_rb_tree_init(&zip->tree, &rb_ops);
@@ -451,7 +465,8 @@ slurp_central_directory(struct archive_read *a, struct zip *zip)
                /* disk_start = archive_le16dec(p + 34); */ /* Better be zero. */
                /* internal_attributes = archive_le16dec(p + 36); */ /* text bit */
                external_attributes = archive_le32dec(p + 38);
-               zip_entry->local_header_offset = archive_le32dec(p + 42);
+               zip_entry->local_header_offset =
+                   archive_le32dec(p + 42) + correction;
 
                /* If we can't guess the mode, leave it zero here;
                   when we read the local file header we might get
index 7239bb16085e7afe6b50ba517e0f79adf87a0002..eba089bc6386c85676765f5c9afb06e2ffaf2805 100644 (file)
@@ -140,6 +140,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_sfx.c
     test_read_large.c
     test_read_pax_truncated.c
     test_read_position.c
diff --git a/libarchive/test/test_read_format_zip_sfx.c b/libarchive/test/test_read_format_zip_sfx.c
new file mode 100644 (file)
index 0000000..50e5fa7
--- /dev/null
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2012 Michihiro NAKAJIMA
+ * 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$");
+
+/*
+ * Read a zip file that is a SFX. 
+ */
+DEFINE_TEST(test_read_format_zip_sfx)
+{
+       const char *refname = "test_read_format_zip_sfx";
+       char *p;
+       size_t s;
+       struct archive *a;
+       struct archive_entry *ae;
+
+       extract_reference_file(refname);
+       p = slurpfile(&s, refname);
+
+       /* Symlinks can only be extracted with the seeking reader. */
+       assert((a = archive_read_new()) != NULL);
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a));
+       assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 1));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("file0", archive_entry_pathname(ae));
+       assertEqualInt(AE_IFREG | 0644, archive_entry_mode(ae));
+
+       assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
+       assertEqualString("build.sh", archive_entry_pathname(ae));
+       assertEqualInt(AE_IFREG | 0755, archive_entry_mode(ae));
+       assertEqualInt(23, archive_entry_size(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));
+}
diff --git a/libarchive/test/test_read_format_zip_sfx.uu b/libarchive/test/test_read_format_zip_sfx.uu
new file mode 100644 (file)
index 0000000..aab730b
--- /dev/null
@@ -0,0 +1,34 @@
+begin 644 test_read_format_zip_sfx
+M!5@J$E]]1]?.)[Z/+RR:J';4YIJ7H0[7:BO"S8^VFB`_M_2)627VRG7%.)ZR
+M->RL72GY3(0UJMJ0;.F=<-36\SK.=/A%FK!K4Z0URPF<&M#E<@RXT`A04/Z\
+M<^0G>R,X8]@8XDDNJY6M`)Q".-::"%RS&VR!DZ_:>D2?J2W="_<P5N5M]]PJ
+M&!O^,VUD!7LUW?771M-Q"KS.HL7P+R/'1._KA6`3?M/8-2LMYS0_`TSQ*]C@
+M>+^EV*LRQR6=M7'6<;4-9>QC><TW/^PNF!Z%=$V1CRF]%XP#023PRV>@*<'9
+M/I<2W=CTNY/`P:EB;N!VD.N^;=8Z)1MJNOW`@8S9Z/X\U4^#H>WZQ>-61Y+W
+M(K*N/]YP(XU?S7^FL2DM15A6H-!:D"W`W/DQN(2IZ12!O<K;KU>_3"Y6MC9`
+MY#9LR=$B?G%0HZZ";I^LT<7@$6%T2#S-DG@K@LJ46)C>A`.T!2P@[Z5T;"DY
+MVE@B9%<XV6"_YO/7%[]"9(-%:-V<-X*GGSJ4?1I72PTMM#X?:XQY)=$QZ2+P
+MQ!HPVXKOE?PXR)A?:+D59>DHX=,"ER*),3<Y?2C-9V<"$L_LO+*'K;E"L0E.
+MQ*C/H*H>-%];VC5,B-`,WNYTNOA[U"LZQ4Q`Y(!"J2SO6JA4>?8[`$P<Z62+
+M+QJ0GOE,=K+N6XOJR8`=][O+>N"E`@URA/B&/),005H.O-.^?T;PF])\WV?/
+M%K*51XKZU_[D_56VA6$UO(-5R<B=M'*\)7\;=`9H0B=#:7EZ/)V_8HPW)]ZY
+M[HXW8KW`]Q`^K;I@0F)@G..KI]]2X6)B<X;X@7Y$:0^V!F#W]GI23)9*?<:G
+MBCNO8DM<']_6[^R%8#]I>6'0T/$S]`("I-`+&!&2>Z-*%PO"D_Q.E:G7<7=[
+MI<^0VIH=CZH9$9^5"W?CGNJ0Y<%R^I(R-M5;9#,.B4;R8['I*P^0%-3("7H(
+M2-#V.4!`(<0=EP,>0S*H?-O[N6'JE`,U`V\<<;=F6L4RZW#1$[,1Z5/-28A?
+M0/ATG:"NW/_TZ('?]7E=9D`5WR`OZN4>7-%DR,5[;$^A,E7QE#[U]F*VZR_H
+M*XX<X1!K_*LESD2GZ2>#+B;Z9*0M(\<#->VZV)%.6&`@!."\7,,/[8,WDDMU
+M2*@5[=A":;?D^<$^*U.UN^B%7M*2^A@`.N)^7"-?@!V9$W$_4[\R"WJ*,Z-$
+M8=9[;;447S.)EED+*4FGT[<U^,V+(J&MAE*0+=7Y!90Y%U\]'JH!^VLMYL0/
+M$@W#!E*A@&A$0[:<8WR8Q%1:OEENQ=.01-<IQD\P`+]0>045[*=AI%;U(1L8
+M\[-R4%15\D,""]:=;;OVAJK.TY\J8A)G&J<JH:2H%!?=XE!+`P0*``````#A
+M@&9!````````````````!0`<`&9I;&4P550)``,6MYA0=SN\4'5X"P`!!/4!
+M```$%````%!+`P0*``````"\>V9!ZECJ?1<````7````"``<`&)U:6QD+G-H
+M550)``-CKIA0=SN\4'5X"P`!!/4!```$%````",A+V)I;B]S:`IE8VAO(")T
+M97-T+B(*4$L!`AX#"@``````X8!F00````````````````4`&```````````
+M`*2!`````&9I;&4P550%``,6MYA0=7@+``$$]0$```04````4$L!`AX#"@``
+M````O'MF0>I8ZGT7````%P````@`&````````0```.V!/P```&)U:6QD+G-H
+M550%``-CKIA0=7@+``$$]0$```04````4$L%!@`````"``(`F0```)@````D
+E`%1H:7,@:7,@82!S86UP;&4@9FEL92!F;W(@:7-S=64@,C4W+@``
+`
+end