libarchive: fix xmalloc_open_zipped_read_close() on NOMMU
authorDenys Vlasenko <vda.linux@googlemail.com>
Mon, 20 Jun 2016 09:06:42 +0000 (11:06 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Mon, 20 Jun 2016 09:06:42 +0000 (11:06 +0200)
The somewhat new "unpack in memory" code was broken
for xmalloc_open_zipped_read_close() on NOMMU: we seek back
over signature, but then expect it to be already consumed.
Stop seeking back in this case.

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
archival/bbunzip.c
archival/libarchive/decompress_gunzip.c
archival/libarchive/decompress_unxz.c
archival/libarchive/open_transformer.c
include/bb_archive.h

index b4f754e0b2ad30ec4f525ef5ba52c98486654673..07ef8617e371e6ae9ebf7ad2219b5c88a927601c 100644 (file)
@@ -121,7 +121,7 @@ int FAST_FUNC bbunpack(char **argv,
 
                if (!(option_mask32 & SEAMLESS_MAGIC)) {
                        init_transformer_state(&xstate);
-                       xstate.check_signature = 1;
+                       xstate.signature_skipped = 0;
                        /*xstate.src_fd = STDIN_FILENO; - already is */
                        xstate.dst_fd = STDOUT_FILENO;
                        status = unpacker(&xstate);
index 20e4d9ac5b9f2b00f85c95457503db3063654a5b..c7fa5b526396481571c1c2b0d44a1dc9a7355512 100644 (file)
@@ -1201,7 +1201,7 @@ unpack_gz_stream(transformer_state_t *xstate)
        if (check_signature16(xstate, GZIP_MAGIC))
                return -1;
 #else
-       if (xstate->check_signature) {
+       if (!xstate->signature_skipped) {
                uint16_t magic2;
 
                if (full_read(xstate->src_fd, &magic2, 2) != 2) {
@@ -1210,7 +1210,7 @@ unpack_gz_stream(transformer_state_t *xstate)
                        return -1;
                }
                if (magic2 == COMPRESS_MAGIC) {
-                       xstate->check_signature = 0;
+                       xstate->signature_skipped = 2;
                        return unpack_Z_stream(xstate);
                }
                if (magic2 != GZIP_MAGIC)
index 1f408abfd4a2e85b0dbab4ea0d55bcf80cafefaf..cd32cc745c35a467643f1bc9a9e05c645649ba94 100644 (file)
@@ -55,7 +55,7 @@ unpack_xz_stream(transformer_state_t *xstate)
        iobuf.out = membuf + BUFSIZ;
        iobuf.out_size = BUFSIZ;
 
-       if (!xstate || xstate->check_signature == 0) {
+       if (!xstate || xstate->signature_skipped) {
                /* Preload XZ file signature */
                strcpy((char*)membuf, HEADER_MAGIC);
                iobuf.in_size = HEADER_MAGIC_SIZE;
index be536a3d7e715f41ef0e1aacd30842092844dc7e..d93c8366f3d569b5a8d15685b45b3166efde5ffb 100644 (file)
@@ -13,16 +13,13 @@ void FAST_FUNC init_transformer_state(transformer_state_t *xstate)
 
 int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
 {
-       if (xstate->check_signature) {
+       if (!xstate->signature_skipped) {
                uint16_t magic2;
                if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
                        bb_error_msg("invalid magic");
-#if 0 /* possible future extension */
-                       if (xstate->check_signature > 1)
-                               xfunc_die();
-#endif
                        return -1;
                }
+               xstate->signature_skipped = 2;
        }
        return 0;
 }
@@ -102,7 +99,7 @@ void check_errors_in_children(int signo)
 /* transformer(), more than meets the eye */
 #if BB_MMU
 void FAST_FUNC fork_transformer(int fd,
-       int check_signature,
+       int signature_skipped,
        IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
 )
 #else
@@ -123,7 +120,7 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
                        IF_DESKTOP(long long) int r;
                        transformer_state_t xstate;
                        init_transformer_state(&xstate);
-                       xstate.check_signature = check_signature;
+                       xstate.signature_skipped = signature_skipped;
                        xstate.src_fd = fd;
                        xstate.dst_fd = fd_pipe.wr;
                        r = transformer(&xstate);
@@ -168,12 +165,11 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
                uint16_t b16[2];
                uint32_t b32[1];
        } magic;
-       int offset;
        transformer_state_t *xstate;
 
-       offset = -2;
        xstate = xzalloc(sizeof(*xstate));
        xstate->src_fd = fd;
+       xstate->signature_skipped = 2;
 
        /* .gz and .bz2 both have 2-byte signature, and their
         * unpack_XXX_stream wants this header skipped. */
@@ -202,7 +198,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
        if (ENABLE_FEATURE_SEAMLESS_XZ
         && magic.b16[0] == XZ_MAGIC1
        ) {
-               offset = -6;
+               xstate->signature_skipped = 6;
                xread(fd, magic.b32, sizeof(magic.b32[0]));
                if (magic.b32[0] == XZ_MAGIC2) {
                        xstate->xformer = unpack_xz_stream;
@@ -226,16 +222,7 @@ static transformer_state_t *setup_transformer_on_fd(int fd, int fail_if_not_comp
 //     USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
        /* fall through to seeking bck over bytes we read earlier */
 
- USE_FOR_NOMMU(found_magic:)
-       /* NOMMU version of fork_transformer execs
-        * an external unzipper that wants
-        * file position at the start of the file.
-        */
-       xlseek(fd, offset, SEEK_CUR);
-
- USE_FOR_MMU(found_magic:)
-       /* In MMU case, if magic was found, seeking back is not necessary */
-
+ found_magic:
        return xstate;
 }
 
@@ -254,6 +241,12 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
 # if BB_MMU
        fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
 # else
+       /* NOMMU version of fork_transformer execs
+        * an external unzipper that wants
+        * file position at the start of the file.
+        */
+       xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
+       xstate->signature_skipped = 0;
        fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
 # endif
        free(xstate);
@@ -300,6 +293,8 @@ int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed)
 # if BB_MMU
                fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
 # else
+               xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
+               xstate->signature_skipped = 0;
                fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
 # endif
        }
index 10969b56780d0466e98c75da0c87f1581e057731..2b9c5f04c649a4c9b492aeea6b6a6fa236ea5390 100644 (file)
@@ -211,7 +211,7 @@ void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
 
 /* Meaning and direction (input/output) of the fields are transformer-specific */
 typedef struct transformer_state_t {
-       smallint check_signature; /* most often referenced member */
+       smallint signature_skipped; /* most often referenced member */
 
        IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
        USE_FOR_NOMMU(const char *xformer_prog;)
@@ -252,11 +252,11 @@ int bbunpack(char **argv,
 void check_errors_in_children(int signo);
 #if BB_MMU
 void fork_transformer(int fd,
-       int check_signature,
+       int signature_skipped,
        IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
 ) FAST_FUNC;
-#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (transformer))
-#define fork_transformer_with_no_sig(fd, transformer)              fork_transformer((fd), 0, (transformer))
+#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 0, (transformer))
+#define fork_transformer_with_no_sig(fd, transformer)              fork_transformer((fd), 1, (transformer))
 #else
 void fork_transformer(int fd, const char *transform_prog) FAST_FUNC;
 #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))