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 <vda.linux@googlemail.com>
This commit is contained in:
Denys Vlasenko 2016-06-20 11:06:42 +02:00
parent ecf25cb5bc
commit 984b0a613a
5 changed files with 23 additions and 28 deletions

View File

@ -121,7 +121,7 @@ int FAST_FUNC bbunpack(char **argv,
if (!(option_mask32 & SEAMLESS_MAGIC)) { if (!(option_mask32 & SEAMLESS_MAGIC)) {
init_transformer_state(&xstate); init_transformer_state(&xstate);
xstate.check_signature = 1; xstate.signature_skipped = 0;
/*xstate.src_fd = STDIN_FILENO; - already is */ /*xstate.src_fd = STDIN_FILENO; - already is */
xstate.dst_fd = STDOUT_FILENO; xstate.dst_fd = STDOUT_FILENO;
status = unpacker(&xstate); status = unpacker(&xstate);

View File

@ -1201,7 +1201,7 @@ unpack_gz_stream(transformer_state_t *xstate)
if (check_signature16(xstate, GZIP_MAGIC)) if (check_signature16(xstate, GZIP_MAGIC))
return -1; return -1;
#else #else
if (xstate->check_signature) { if (!xstate->signature_skipped) {
uint16_t magic2; uint16_t magic2;
if (full_read(xstate->src_fd, &magic2, 2) != 2) { if (full_read(xstate->src_fd, &magic2, 2) != 2) {
@ -1210,7 +1210,7 @@ unpack_gz_stream(transformer_state_t *xstate)
return -1; return -1;
} }
if (magic2 == COMPRESS_MAGIC) { if (magic2 == COMPRESS_MAGIC) {
xstate->check_signature = 0; xstate->signature_skipped = 2;
return unpack_Z_stream(xstate); return unpack_Z_stream(xstate);
} }
if (magic2 != GZIP_MAGIC) if (magic2 != GZIP_MAGIC)

View File

@ -55,7 +55,7 @@ unpack_xz_stream(transformer_state_t *xstate)
iobuf.out = membuf + BUFSIZ; iobuf.out = membuf + BUFSIZ;
iobuf.out_size = BUFSIZ; iobuf.out_size = BUFSIZ;
if (!xstate || xstate->check_signature == 0) { if (!xstate || xstate->signature_skipped) {
/* Preload XZ file signature */ /* Preload XZ file signature */
strcpy((char*)membuf, HEADER_MAGIC); strcpy((char*)membuf, HEADER_MAGIC);
iobuf.in_size = HEADER_MAGIC_SIZE; iobuf.in_size = HEADER_MAGIC_SIZE;

View 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) int FAST_FUNC check_signature16(transformer_state_t *xstate, unsigned magic16)
{ {
if (xstate->check_signature) { if (!xstate->signature_skipped) {
uint16_t magic2; uint16_t magic2;
if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) { if (full_read(xstate->src_fd, &magic2, 2) != 2 || magic2 != magic16) {
bb_error_msg("invalid magic"); bb_error_msg("invalid magic");
#if 0 /* possible future extension */
if (xstate->check_signature > 1)
xfunc_die();
#endif
return -1; return -1;
} }
xstate->signature_skipped = 2;
} }
return 0; return 0;
} }
@ -102,7 +99,7 @@ void check_errors_in_children(int signo)
/* transformer(), more than meets the eye */ /* transformer(), more than meets the eye */
#if BB_MMU #if BB_MMU
void FAST_FUNC fork_transformer(int fd, 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) IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
) )
#else #else
@ -123,7 +120,7 @@ void FAST_FUNC fork_transformer(int fd, const char *transform_prog)
IF_DESKTOP(long long) int r; IF_DESKTOP(long long) int r;
transformer_state_t xstate; transformer_state_t xstate;
init_transformer_state(&xstate); init_transformer_state(&xstate);
xstate.check_signature = check_signature; xstate.signature_skipped = signature_skipped;
xstate.src_fd = fd; xstate.src_fd = fd;
xstate.dst_fd = fd_pipe.wr; xstate.dst_fd = fd_pipe.wr;
r = transformer(&xstate); 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]; uint16_t b16[2];
uint32_t b32[1]; uint32_t b32[1];
} magic; } magic;
int offset;
transformer_state_t *xstate; transformer_state_t *xstate;
offset = -2;
xstate = xzalloc(sizeof(*xstate)); xstate = xzalloc(sizeof(*xstate));
xstate->src_fd = fd; xstate->src_fd = fd;
xstate->signature_skipped = 2;
/* .gz and .bz2 both have 2-byte signature, and their /* .gz and .bz2 both have 2-byte signature, and their
* unpack_XXX_stream wants this header skipped. */ * 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 if (ENABLE_FEATURE_SEAMLESS_XZ
&& magic.b16[0] == XZ_MAGIC1 && magic.b16[0] == XZ_MAGIC1
) { ) {
offset = -6; xstate->signature_skipped = 6;
xread(fd, magic.b32, sizeof(magic.b32[0])); xread(fd, magic.b32, sizeof(magic.b32[0]));
if (magic.b32[0] == XZ_MAGIC2) { if (magic.b32[0] == XZ_MAGIC2) {
xstate->xformer = unpack_xz_stream; 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";) // USE_FOR_NOMMU(xstate->xformer_prog = "cat";)
/* fall through to seeking bck over bytes we read earlier */ /* fall through to seeking bck over bytes we read earlier */
USE_FOR_NOMMU(found_magic:) 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 */
return xstate; return xstate;
} }
@ -254,6 +241,12 @@ int FAST_FUNC setup_unzip_on_fd(int fd, int fail_if_not_compressed)
# if BB_MMU # if BB_MMU
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
# else # 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); fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
# endif # endif
free(xstate); free(xstate);
@ -300,6 +293,8 @@ int FAST_FUNC open_zipped(const char *fname, int fail_if_not_compressed)
# if BB_MMU # if BB_MMU
fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer); fork_transformer_with_no_sig(xstate->src_fd, xstate->xformer);
# else # else
xlseek(fd, - xstate->signature_skipped, SEEK_CUR);
xstate->signature_skipped = 0;
fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog); fork_transformer_with_sig(xstate->src_fd, xstate->xformer, xstate->xformer_prog);
# endif # endif
} }

View File

@ -211,7 +211,7 @@ void dealloc_bunzip(bunzip_data *bd) FAST_FUNC;
/* Meaning and direction (input/output) of the fields are transformer-specific */ /* Meaning and direction (input/output) of the fields are transformer-specific */
typedef struct transformer_state_t { 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); IF_DESKTOP(long long) int FAST_FUNC (*xformer)(struct transformer_state_t *xstate);
USE_FOR_NOMMU(const char *xformer_prog;) USE_FOR_NOMMU(const char *xformer_prog;)
@ -252,11 +252,11 @@ int bbunpack(char **argv,
void check_errors_in_children(int signo); void check_errors_in_children(int signo);
#if BB_MMU #if BB_MMU
void fork_transformer(int fd, void fork_transformer(int fd,
int check_signature, int signature_skipped,
IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate) IF_DESKTOP(long long) int FAST_FUNC (*transformer)(transformer_state_t *xstate)
) FAST_FUNC; ) FAST_FUNC;
#define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), 1, (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), 0, (transformer)) #define fork_transformer_with_no_sig(fd, transformer) fork_transformer((fd), 1, (transformer))
#else #else
void fork_transformer(int fd, const char *transform_prog) FAST_FUNC; 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)) #define fork_transformer_with_sig(fd, transformer, transform_prog) fork_transformer((fd), (transform_prog))