diff options
author | Denis Vlasenko | 2008-02-04 12:12:48 +0000 |
---|---|---|
committer | Denis Vlasenko | 2008-02-04 12:12:48 +0000 |
commit | e8ef7ec7de0cd9906b42a94eddb800ed1229a614 (patch) | |
tree | 77596e96a82e367b23c986c9259680990df0edf2 | |
parent | f3f33ebb0b325a0a5710cb39530449dd09c5ab70 (diff) | |
download | busybox-e8ef7ec7de0cd9906b42a94eddb800ed1229a614.zip busybox-e8ef7ec7de0cd9906b42a94eddb800ed1229a614.tar.gz |
unzip: do not try to read entire compressed stream at once (it can be huge)
unzip: handle short reads correctly
-rw-r--r-- | archival/libunarchive/decompress_unzip.c | 23 | ||||
-rw-r--r-- | include/unarchive.h | 2 |
2 files changed, 18 insertions, 7 deletions
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index 04d6f15..a764fbc 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c @@ -85,7 +85,8 @@ typedef struct state_t { /* input (compressed) data */ unsigned char *bytebuffer; /* buffer itself */ - unsigned bytebuffer_max; /* buffer size */ + off_t to_read; /* compressed bytes to read (unzip only, -1 for gunzip) */ +// unsigned bytebuffer_max; /* buffer size */ unsigned bytebuffer_offset; /* buffer position */ unsigned bytebuffer_size; /* how much data is there (size <= max) */ @@ -126,7 +127,10 @@ typedef struct state_t { #define gunzip_crc_table (S()gunzip_crc_table ) #define gunzip_bb (S()gunzip_bb ) #define gunzip_bk (S()gunzip_bk ) -#define bytebuffer_max (S()bytebuffer_max ) +#define to_read (S()to_read ) +// #define bytebuffer_max (S()bytebuffer_max ) +// Both gunzip and unzip can use constant buffer size now (16k): +#define bytebuffer_max 0x4000 #define bytebuffer (S()bytebuffer ) #define bytebuffer_offset (S()bytebuffer_offset ) #define bytebuffer_size (S()bytebuffer_size ) @@ -251,13 +255,18 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current { while (*current < required) { if (bytebuffer_offset >= bytebuffer_size) { + unsigned sz = bytebuffer_max - 4; + if (to_read >= 0 && to_read < sz) /* unzip only */ + sz = to_read; /* Leave the first 4 bytes empty so we can always unwind the bitbuffer * to the front of the bytebuffer */ - bytebuffer_size = safe_read(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 4); + bytebuffer_size = safe_read(gunzip_src_fd, &bytebuffer[4], sz); if ((int)bytebuffer_size < 1) { error_msg = "unexpected end of file"; abort_unzip(PASS_STATE_ONLY); } + if (to_read >= 0) /* unzip only */ + to_read -= bytebuffer_size; bytebuffer_size += 4; bytebuffer_offset = 4; } @@ -1025,14 +1034,15 @@ inflate_unzip_internal(STATE_PARAM int in, int out) /* For unzip */ USE_DESKTOP(long long) int -inflate_unzip(inflate_unzip_result *res, unsigned bufsize, int in, int out) +inflate_unzip(inflate_unzip_result *res, off_t compr_size, int in, int out) { USE_DESKTOP(long long) int n; DECLARE_STATE; ALLOC_STATE; - bytebuffer_max = bufsize + 4; + to_read = compr_size; +// bytebuffer_max = 0x8000; bytebuffer_offset = 4; bytebuffer = xmalloc(bytebuffer_max); n = inflate_unzip_internal(PASS_STATE in, out); @@ -1176,7 +1186,8 @@ unpack_gz_stream(int in, int out) n = 0; ALLOC_STATE; - bytebuffer_max = 0x8000; + to_read = -1; +// bytebuffer_max = 0x8000; bytebuffer = xmalloc(bytebuffer_max); gunzip_src_fd = in; diff --git a/include/unarchive.h b/include/unarchive.h index 00a00d6..e8beebb 100644 --- a/include/unarchive.h +++ b/include/unarchive.h @@ -109,7 +109,7 @@ typedef struct inflate_unzip_result { } inflate_unzip_result; extern USE_DESKTOP(long long) int unpack_bz2_stream(int src_fd, int dst_fd); -extern USE_DESKTOP(long long) int inflate_unzip(inflate_unzip_result *res, unsigned bufsize, int src_fd, int dst_fd); +extern USE_DESKTOP(long long) int inflate_unzip(inflate_unzip_result *res, off_t compr_size, int src_fd, int dst_fd); extern USE_DESKTOP(long long) int unpack_gz_stream(int src_fd, int dst_fd); extern USE_DESKTOP(long long) int unpack_lzma_stream(int src_fd, int dst_fd); |