From 984b0a613aaf1cdf48c2e2af08c8466a7bad8307 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 20 Jun 2016 11:06:42 +0200 Subject: [PATCH] libarchive: fix xmalloc_open_zipped_read_close() on NOMMU 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 --- archival/bbunzip.c | 2 +- archival/libarchive/decompress_gunzip.c | 4 +-- archival/libarchive/decompress_unxz.c | 2 +- archival/libarchive/open_transformer.c | 35 +++++++++++-------------- include/bb_archive.h | 8 +++--- 5 files changed, 23 insertions(+), 28 deletions(-) diff --git a/archival/bbunzip.c b/archival/bbunzip.c index b4f754e0b..07ef8617e 100644 --- a/archival/bbunzip.c +++ b/archival/bbunzip.c @@ -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); diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index 20e4d9ac5..c7fa5b526 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c @@ -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) diff --git a/archival/libarchive/decompress_unxz.c b/archival/libarchive/decompress_unxz.c index 1f408abfd..cd32cc745 100644 --- a/archival/libarchive/decompress_unxz.c +++ b/archival/libarchive/decompress_unxz.c @@ -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; diff --git a/archival/libarchive/open_transformer.c b/archival/libarchive/open_transformer.c index be536a3d7..d93c8366f 100644 --- a/archival/libarchive/open_transformer.c +++ b/archival/libarchive/open_transformer.c @@ -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 } diff --git a/include/bb_archive.h b/include/bb_archive.h index 10969b567..2b9c5f04c 100644 --- a/include/bb_archive.h +++ b/include/bb_archive.h @@ -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))