From: Michihiro NAKAJIMA Date: Mon, 3 Dec 2012 05:59:18 +0000 (+0900) Subject: Fix issue 257. Revise zip header offsets for reading SFX. X-Git-Tag: v3.1.0~24 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f0ce82aaa4adc138dd87694b8462fe70f96a81bb;p=thirdparty%2Flibarchive.git Fix issue 257. Revise zip header offsets for reading SFX. --- diff --git a/Makefile.am b/Makefile.am index 1c7c8cbef..c395bb279 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/libarchive/archive_read_support_format_zip.c b/libarchive/archive_read_support_format_zip.c index 362621f38..fd06b0bed 100644 --- a/libarchive/archive_read_support_format_zip.c +++ b/libarchive/archive_read_support_format_zip.c @@ -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 diff --git a/libarchive/test/CMakeLists.txt b/libarchive/test/CMakeLists.txt index 7239bb160..eba089bc6 100644 --- a/libarchive/test/CMakeLists.txt +++ b/libarchive/test/CMakeLists.txt @@ -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 index 000000000..50e5fa723 --- /dev/null +++ b/libarchive/test/test_read_format_zip_sfx.c @@ -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 index 000000000..aab730ba8 --- /dev/null +++ b/libarchive/test/test_read_format_zip_sfx.uu @@ -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="_+^EV*LRQR6=M7'6<;4-9>QC>@*<'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_3"Y6MC9` +MY#9LR=$B?G%0HZZ";I^LT<7@$6%T2#S-DG@K@LJ46)C>A`.T!2P@[Z5T;"DY +MVE@B9%DHX=,"ER*),3-%];VC5,B-`,WNYTNOA[U"LZQ4Q`Y(!"J2SO6JA4>?8[`$PN"E`@URA/B&/),005H.O-.^?T;PF])\WV?/ +M%K*51XKZU_[D_56VA6$UO(-5R6'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#+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[045[*=AI%;U(1L8 +M\[-R4%15\D,""]:=;;OVAJK.TY\J8A)G&JV9!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