From c6758a07c68033627a692cda27aebc8f6a662e7f Mon Sep 17 00:00:00 2001 From: Denis Vlasenko Date: Tue, 10 Apr 2007 21:40:19 +0000 Subject: make compressed help code NOMMU- and NOFORK-friendly - no forking anymore, bunzip2 unpack routine now does all it in memory. --- archival/libunarchive/decompress_bunzip2.c | 58 ++++++++++++++++++------------ archival/libunarchive/decompress_unzip.c | 2 +- archival/libunarchive/get_header_tar_gz.c | 2 -- 3 files changed, 37 insertions(+), 25 deletions(-) (limited to 'archival/libunarchive') diff --git a/archival/libunarchive/decompress_bunzip2.c b/archival/libunarchive/decompress_bunzip2.c index d4db40ece..3f0b0f6f2 100644 --- a/archival/libunarchive/decompress_bunzip2.c +++ b/archival/libunarchive/decompress_bunzip2.c @@ -62,34 +62,31 @@ struct group_data { /* Structure holding all the housekeeping data, including IO buffers and memory that persists between calls to bunzip */ -typedef struct { +struct bunzip_data { /* State for interrupting output loop */ - int writeCopies, writePos, writeRunCountdown, writeCount, writeCurrent; /* I/O tracking data (file handles, buffers, positions, etc.) */ - int in_fd, out_fd, inbufCount, inbufPos /*, outbufPos*/; unsigned char *inbuf /*,*outbuf*/; unsigned inbufBitCount, inbufBits; /* The CRC values stored in the block header and calculated from the data */ - uint32_t headerCRC, totalCRC, writeCRC; - uint32_t *crc32Table; - /* Intermediate buffer and its size (in bytes) */ + /* Intermediate buffer and its size (in bytes) */ unsigned *dbuf, dbufSize; - /* These things are a bit too big to go on the stack */ + /* For I/O error handling */ + jmp_buf jmpbuf; + /* Big things go last (register-relative addressing can be larger for big offsets */ + uint32_t crc32Table[256]; unsigned char selectors[32768]; /* nSelectors=15 bits */ struct group_data groups[MAX_GROUPS]; /* Huffman coding tables */ +}; +/* typedef struct bunzip_data bunzip_data; -- done in .h file */ - /* For I/O error handling */ - - jmp_buf jmpbuf; -} bunzip_data; /* Return the next nnn bits of input. All reads from the compressed input are done through this function. All reads are big endian */ @@ -106,6 +103,7 @@ static unsigned get_bits(bunzip_data *bd, char bits_wanted) /* If we need to read more data from file into byte buffer, do so */ if (bd->inbufPos == bd->inbufCount) { + /* if "no input fd" case: in_fd == -1, read fails, we jump */ bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE); if (bd->inbufCount <= 0) longjmp(bd->jmpbuf, RETVAL_UNEXPECTED_INPUT_EOF); @@ -519,7 +517,7 @@ static int get_next_block(bunzip_data *bd) are ignored, data is written to out_fd and return is RETVAL_OK or error. */ -static int read_bunzip(bunzip_data *bd, char *outbuf, int len) +int read_bunzip(bunzip_data *bd, char *outbuf, int len) { const unsigned *dbuf; int pos, current, previous, gotcount; @@ -627,11 +625,16 @@ static int read_bunzip(bunzip_data *bd, char *outbuf, int len) goto decode_next_byte; } + /* Allocate the structure, read file header. If in_fd==-1, inbuf must contain a complete bunzip file (len bytes long). If in_fd!=-1, inbuf and len are ignored, and data is read from file handle into temporary buffer. */ -static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf, +/* Because bunzip2 is used for help text unpacking, and because bb_show_usage() + should work for NOFORK applets too, we must be extremely careful to not leak + any allocations! */ + +int start_bunzip(bunzip_data **bdp, int in_fd, const unsigned char *inbuf, int len) { bunzip_data *bd; @@ -653,14 +656,15 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf, bd->in_fd = in_fd; if (-1 == in_fd) { - bd->inbuf = inbuf; + /* in this case, bd->inbuf is read-only */ + bd->inbuf = (void*)inbuf; /* cast away const-ness */ bd->inbufCount = len; } else bd->inbuf = (unsigned char *)(bd + 1); /* Init the CRC32 table (big endian) */ - bd->crc32Table = crc32_filltable(1); + crc32_filltable(bd->crc32Table, 1); /* Setup for I/O error handling via longjmp */ @@ -670,19 +674,30 @@ static int start_bunzip(bunzip_data **bdp, int in_fd, unsigned char *inbuf, /* Ensure that file starts with "BZh['1'-'9']." */ i = get_bits(bd, 32); - if (((unsigned)(i - BZh0 - 1)) >= 9) return RETVAL_NOT_BZIP_DATA; + if ((unsigned)(i - BZh0 - 1) >= 9) return RETVAL_NOT_BZIP_DATA; /* Fourth byte (ascii '1'-'9'), indicates block size in units of 100k of uncompressed data. Allocate intermediate buffer for block. */ bd->dbufSize = 100000 * (i - BZh0); - bd->dbuf = xmalloc(bd->dbufSize * sizeof(int)); + /* Cannot use xmalloc - may leak bd in NOFORK case! */ + bd->dbuf = malloc_or_warn(bd->dbufSize * sizeof(int)); + if (!bd->dbuf) { + free(bd); + xfunc_die(); + } return RETVAL_OK; } -/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, - not end of file.) */ +void dealloc_bunzip(bunzip_data *bd) +{ + free(bd->dbuf); + free(bd); +} + + +/* Decompress src_fd to dst_fd. Stops at end of bzip data, not end of file. */ USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd) @@ -693,7 +708,7 @@ uncompressStream(int src_fd, int dst_fd) int i; outbuf = xmalloc(IOBUF_SIZE); - i = start_bunzip(&bd, src_fd, 0, 0); + i = start_bunzip(&bd, src_fd, NULL, 0); if (!i) { for (;;) { i = read_bunzip(bd, outbuf, IOBUF_SIZE); @@ -719,8 +734,7 @@ uncompressStream(int src_fd, int dst_fd) } else { bb_error_msg("decompression failed"); } - free(bd->dbuf); - free(bd); + dealloc_bunzip(bd); free(outbuf); return i ? i : USE_DESKTOP(total_written) + 0; diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index 331fe34d8..19ce5097a 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c @@ -1000,7 +1000,7 @@ inflate_unzip_internal(STATE_PARAM int in, int out) gunzip_bb = 0; /* Create the crc table */ - gunzip_crc_table = crc32_filltable(0); + gunzip_crc_table = crc32_filltable(NULL, 0); gunzip_crc = ~0; /* Allocate space for buffer */ diff --git a/archival/libunarchive/get_header_tar_gz.c b/archival/libunarchive/get_header_tar_gz.c index 1f07e4e64..69126e0ba 100644 --- a/archival/libunarchive/get_header_tar_gz.c +++ b/archival/libunarchive/get_header_tar_gz.c @@ -3,8 +3,6 @@ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ -#include - #include "libbb.h" #include "unarchive.h" -- cgit v1.2.3