diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-04 12:12:48 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-04 12:12:48 +0000 |
commit | e8ef7ec7de0cd9906b42a94eddb800ed1229a614 (patch) | |
tree | 77596e96a82e367b23c986c9259680990df0edf2 /archival/libunarchive | |
parent | f3f33ebb0b325a0a5710cb39530449dd09c5ab70 (diff) | |
download | busybox-w32-e8ef7ec7de0cd9906b42a94eddb800ed1229a614.tar.gz busybox-w32-e8ef7ec7de0cd9906b42a94eddb800ed1229a614.tar.bz2 busybox-w32-e8ef7ec7de0cd9906b42a94eddb800ed1229a614.zip |
unzip: do not try to read entire compressed stream at once (it can be huge)
unzip: handle short reads correctly
Diffstat (limited to 'archival/libunarchive')
-rw-r--r-- | archival/libunarchive/decompress_unzip.c | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/archival/libunarchive/decompress_unzip.c b/archival/libunarchive/decompress_unzip.c index 04d6f1556..a764fbc98 100644 --- a/archival/libunarchive/decompress_unzip.c +++ b/archival/libunarchive/decompress_unzip.c | |||
@@ -85,7 +85,8 @@ typedef struct state_t { | |||
85 | 85 | ||
86 | /* input (compressed) data */ | 86 | /* input (compressed) data */ |
87 | unsigned char *bytebuffer; /* buffer itself */ | 87 | unsigned char *bytebuffer; /* buffer itself */ |
88 | unsigned bytebuffer_max; /* buffer size */ | 88 | off_t to_read; /* compressed bytes to read (unzip only, -1 for gunzip) */ |
89 | // unsigned bytebuffer_max; /* buffer size */ | ||
89 | unsigned bytebuffer_offset; /* buffer position */ | 90 | unsigned bytebuffer_offset; /* buffer position */ |
90 | unsigned bytebuffer_size; /* how much data is there (size <= max) */ | 91 | unsigned bytebuffer_size; /* how much data is there (size <= max) */ |
91 | 92 | ||
@@ -126,7 +127,10 @@ typedef struct state_t { | |||
126 | #define gunzip_crc_table (S()gunzip_crc_table ) | 127 | #define gunzip_crc_table (S()gunzip_crc_table ) |
127 | #define gunzip_bb (S()gunzip_bb ) | 128 | #define gunzip_bb (S()gunzip_bb ) |
128 | #define gunzip_bk (S()gunzip_bk ) | 129 | #define gunzip_bk (S()gunzip_bk ) |
129 | #define bytebuffer_max (S()bytebuffer_max ) | 130 | #define to_read (S()to_read ) |
131 | // #define bytebuffer_max (S()bytebuffer_max ) | ||
132 | // Both gunzip and unzip can use constant buffer size now (16k): | ||
133 | #define bytebuffer_max 0x4000 | ||
130 | #define bytebuffer (S()bytebuffer ) | 134 | #define bytebuffer (S()bytebuffer ) |
131 | #define bytebuffer_offset (S()bytebuffer_offset ) | 135 | #define bytebuffer_offset (S()bytebuffer_offset ) |
132 | #define bytebuffer_size (S()bytebuffer_size ) | 136 | #define bytebuffer_size (S()bytebuffer_size ) |
@@ -251,13 +255,18 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current | |||
251 | { | 255 | { |
252 | while (*current < required) { | 256 | while (*current < required) { |
253 | if (bytebuffer_offset >= bytebuffer_size) { | 257 | if (bytebuffer_offset >= bytebuffer_size) { |
258 | unsigned sz = bytebuffer_max - 4; | ||
259 | if (to_read >= 0 && to_read < sz) /* unzip only */ | ||
260 | sz = to_read; | ||
254 | /* Leave the first 4 bytes empty so we can always unwind the bitbuffer | 261 | /* Leave the first 4 bytes empty so we can always unwind the bitbuffer |
255 | * to the front of the bytebuffer */ | 262 | * to the front of the bytebuffer */ |
256 | bytebuffer_size = safe_read(gunzip_src_fd, &bytebuffer[4], bytebuffer_max - 4); | 263 | bytebuffer_size = safe_read(gunzip_src_fd, &bytebuffer[4], sz); |
257 | if ((int)bytebuffer_size < 1) { | 264 | if ((int)bytebuffer_size < 1) { |
258 | error_msg = "unexpected end of file"; | 265 | error_msg = "unexpected end of file"; |
259 | abort_unzip(PASS_STATE_ONLY); | 266 | abort_unzip(PASS_STATE_ONLY); |
260 | } | 267 | } |
268 | if (to_read >= 0) /* unzip only */ | ||
269 | to_read -= bytebuffer_size; | ||
261 | bytebuffer_size += 4; | 270 | bytebuffer_size += 4; |
262 | bytebuffer_offset = 4; | 271 | bytebuffer_offset = 4; |
263 | } | 272 | } |
@@ -1025,14 +1034,15 @@ inflate_unzip_internal(STATE_PARAM int in, int out) | |||
1025 | /* For unzip */ | 1034 | /* For unzip */ |
1026 | 1035 | ||
1027 | USE_DESKTOP(long long) int | 1036 | USE_DESKTOP(long long) int |
1028 | inflate_unzip(inflate_unzip_result *res, unsigned bufsize, int in, int out) | 1037 | inflate_unzip(inflate_unzip_result *res, off_t compr_size, int in, int out) |
1029 | { | 1038 | { |
1030 | USE_DESKTOP(long long) int n; | 1039 | USE_DESKTOP(long long) int n; |
1031 | DECLARE_STATE; | 1040 | DECLARE_STATE; |
1032 | 1041 | ||
1033 | ALLOC_STATE; | 1042 | ALLOC_STATE; |
1034 | 1043 | ||
1035 | bytebuffer_max = bufsize + 4; | 1044 | to_read = compr_size; |
1045 | // bytebuffer_max = 0x8000; | ||
1036 | bytebuffer_offset = 4; | 1046 | bytebuffer_offset = 4; |
1037 | bytebuffer = xmalloc(bytebuffer_max); | 1047 | bytebuffer = xmalloc(bytebuffer_max); |
1038 | n = inflate_unzip_internal(PASS_STATE in, out); | 1048 | n = inflate_unzip_internal(PASS_STATE in, out); |
@@ -1176,7 +1186,8 @@ unpack_gz_stream(int in, int out) | |||
1176 | n = 0; | 1186 | n = 0; |
1177 | 1187 | ||
1178 | ALLOC_STATE; | 1188 | ALLOC_STATE; |
1179 | bytebuffer_max = 0x8000; | 1189 | to_read = -1; |
1190 | // bytebuffer_max = 0x8000; | ||
1180 | bytebuffer = xmalloc(bytebuffer_max); | 1191 | bytebuffer = xmalloc(bytebuffer_max); |
1181 | gunzip_src_fd = in; | 1192 | gunzip_src_fd = in; |
1182 | 1193 | ||