do not expose internal state of [g]zip unpacker.

fix memory leak in inflate_gunzip.
This commit is contained in:
Denis Vlasenko 2007-01-05 23:56:53 +00:00
parent 447b543eaf
commit cd42cb8df0
3 changed files with 51 additions and 47 deletions

View File

@ -45,9 +45,8 @@ typedef struct huft_s {
} v; } v;
} huft_t; } huft_t;
/* Globally-visible data */ static off_t gunzip_bytes_out; /* number of output bytes */
off_t gunzip_bytes_out; /* number of output bytes */ static uint32_t gunzip_crc;
uint32_t gunzip_crc;
static int gunzip_src_fd; static int gunzip_src_fd;
static unsigned gunzip_outbuf_count; /* bytes in output buffer */ static unsigned gunzip_outbuf_count; /* bytes in output buffer */
@ -165,8 +164,7 @@ static int huft_free(huft_t * t)
* t: result: starting table * t: result: starting table
* m: maximum lookup bits, returns actual * m: maximum lookup bits, returns actual
*/ */
static static int huft_build(unsigned *b, const unsigned n,
int huft_build(unsigned *b, const unsigned n,
const unsigned s, const unsigned short *d, const unsigned s, const unsigned short *d,
const unsigned char *e, huft_t ** t, unsigned *m) const unsigned char *e, huft_t ** t, unsigned *m)
{ {
@ -408,7 +406,6 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, c
return 1; // We have a block to read return 1; // We have a block to read
} }
} else { /* it's an EOB or a length */ } else { /* it's an EOB or a length */
/* exit if end of block */ /* exit if end of block */
if (e == 15) { if (e == 15) {
break; break;
@ -595,11 +592,11 @@ static int inflate_block(int *e)
inflate_stored(n, b_stored, k_stored, 1); // Setup inflate_stored inflate_stored(n, b_stored, k_stored, 1); // Setup inflate_stored
return -1; return -1;
} }
case 1: /* Inflate fixed case 1:
* decompress an inflated type 1 (fixed Huffman codes) block. We should /* Inflate fixed
* either replace this with a custom decoder, or at least precompute the * decompress an inflated type 1 (fixed Huffman codes) block. We should
* Huffman tables. * either replace this with a custom decoder, or at least precompute the
*/ * Huffman tables. */
{ {
int i; /* temporary variable */ int i; /* temporary variable */
huft_t *tl; /* literal/length code table */ huft_t *tl; /* literal/length code table */
@ -854,25 +851,10 @@ static int inflate_get_next_window(void)
/* Doesnt get here */ /* Doesnt get here */
} }
/* Initialize bytebuffer, be careful not to overfill the buffer */
/* Called from archival/unzip.c */
void inflate_init(unsigned bufsize)
{
/* Set the bytebuffer size, default is same as gunzip_wsize */
bytebuffer_max = bufsize + 8;
bytebuffer_offset = 4;
bytebuffer_size = 0;
}
/* Called from archival/unzip.c */
void inflate_cleanup(void)
{
free(bytebuffer);
}
/* Called from inflate_gunzip() and archival/unzip.c */ /* Called from inflate_gunzip() and archival/unzip.c */
USE_DESKTOP(long long) int static USE_DESKTOP(long long) int
inflate_unzip(int in, int out) inflate_unzip_internal(int in, int out)
{ {
USE_DESKTOP(long long total = 0;) USE_DESKTOP(long long total = 0;)
ssize_t nwrote; ssize_t nwrote;
@ -922,14 +904,35 @@ inflate_unzip(int in, int out)
return USE_DESKTOP(total) + 0; return USE_DESKTOP(total) + 0;
} }
USE_DESKTOP(long long) int
inflate_unzip(inflate_unzip_result *res, unsigned bufsize, int in, int out)
{
USE_DESKTOP(long long) int n;
bytebuffer_max = bufsize + 8;
bytebuffer_offset = 4;
bytebuffer_size = 0;
n = inflate_unzip_internal(in, out);
res->crc = gunzip_crc;
res->bytes_out = gunzip_bytes_out;
free(bytebuffer);
return n;
}
USE_DESKTOP(long long) int USE_DESKTOP(long long) int
inflate_gunzip(int in, int out) inflate_gunzip(int in, int out)
{ {
uint32_t stored_crc = 0; uint32_t stored_crc = 0;
unsigned count; unsigned count;
USE_DESKTOP(long long total = )inflate_unzip(in, out); USE_DESKTOP(long long) int n;
USE_DESKTOP(if (total < 0) return total;) n = inflate_unzip_internal(in, out);
if (n < 0) goto ret;
/* top up the input buffer with the rest of the trailer */ /* top up the input buffer with the rest of the trailer */
count = bytebuffer_size - bytebuffer_offset; count = bytebuffer_size - bytebuffer_offset;
@ -946,7 +949,8 @@ inflate_gunzip(int in, int out)
/* Validate decompression - crc */ /* Validate decompression - crc */
if (stored_crc != (~gunzip_crc)) { if (stored_crc != (~gunzip_crc)) {
bb_error_msg("crc error"); bb_error_msg("crc error");
return -1; n = -1;
goto ret;
} }
/* Validate decompression - size */ /* Validate decompression - size */
@ -955,8 +959,9 @@ inflate_gunzip(int in, int out)
(bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24)) (bytebuffer[bytebuffer_offset+2] << 16) | (bytebuffer[bytebuffer_offset+3] << 24))
) { ) {
bb_error_msg("incorrect length"); bb_error_msg("incorrect length");
return -1; n = -1;
} }
ret:
return USE_DESKTOP(total) + 0; free(bytebuffer);
return n;
} }

View File

@ -76,16 +76,16 @@ static int unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd)
bb_copyfd_exact_size(src_fd, dst_fd, size); bb_copyfd_exact_size(src_fd, dst_fd, size);
} else { } else {
/* Method 8 - inflate */ /* Method 8 - inflate */
inflate_init(zip_header->formatted.cmpsize); inflate_unzip_result res;
inflate_unzip(src_fd, dst_fd); /* err = */ inflate_unzip(&res, zip_header->formatted.cmpsize, src_fd, dst_fd);
inflate_cleanup(); // we should check for -1 error return
/* Validate decompression - crc */ /* Validate decompression - crc */
if (zip_header->formatted.crc32 != (gunzip_crc ^ 0xffffffffL)) { if (zip_header->formatted.crc32 != (res.crc ^ 0xffffffffL)) {
bb_error_msg("invalid compressed data--%s error", "crc"); bb_error_msg("invalid compressed data--%s error", "crc");
return 1; return 1;
} }
/* Validate decompression - size */ /* Validate decompression - size */
if (zip_header->formatted.ucmpsize != gunzip_bytes_out) { if (zip_header->formatted.ucmpsize != res.bytes_out) {
bb_error_msg("invalid compressed data--%s error", "length"); bb_error_msg("invalid compressed data--%s error", "length");
return 1; return 1;
} }

View File

@ -65,10 +65,6 @@ typedef struct archive_handle_s {
} archive_handle_t; } archive_handle_t;
extern uint32_t gunzip_crc;
extern off_t gunzip_bytes_out;
extern archive_handle_t *init_handle(void); extern archive_handle_t *init_handle(void);
extern char filter_accept_all(archive_handle_t *archive_handle); extern char filter_accept_all(archive_handle_t *archive_handle);
@ -106,14 +102,17 @@ extern const llist_t *find_list_entry(const llist_t *list, const char *filename)
extern const llist_t *find_list_entry2(const llist_t *list, const char *filename); extern const llist_t *find_list_entry2(const llist_t *list, const char *filename);
extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd); extern USE_DESKTOP(long long) int uncompressStream(int src_fd, int dst_fd);
extern void inflate_init(unsigned int bufsize);
extern void inflate_cleanup(void); typedef struct inflate_unzip_result {
extern USE_DESKTOP(long long) int inflate_unzip(int in, int out); off_t bytes_out;
uint32_t crc;
} inflate_unzip_result;
extern USE_DESKTOP(long long) int inflate_unzip(inflate_unzip_result *res, unsigned bufsize, int in, int out);
extern USE_DESKTOP(long long) int inflate_gunzip(int in, int out); extern USE_DESKTOP(long long) int inflate_gunzip(int in, int out);
extern USE_DESKTOP(long long) int unlzma(int src_fd, int dst_fd); extern USE_DESKTOP(long long) int unlzma(int src_fd, int dst_fd);
extern int open_transformer(int src_fd, extern int open_transformer(int src_fd,
USE_DESKTOP(long long) int (*transformer)(int src_fd, int dst_fd)); USE_DESKTOP(long long) int (*transformer)(int src_fd, int dst_fd));
#endif #endif