diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-14 21:15:25 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-04-14 21:15:25 +0200 |
commit | afc766fc12d54670aaed9bbb228efc7a5be561db (patch) | |
tree | 6c3416536a992b40982924099831cb54091cee3a | |
parent | 1a45b2ccea94b0fc123798f276a0801413597880 (diff) | |
download | busybox-w32-afc766fc12d54670aaed9bbb228efc7a5be561db.tar.gz busybox-w32-afc766fc12d54670aaed9bbb228efc7a5be561db.tar.bz2 busybox-w32-afc766fc12d54670aaed9bbb228efc7a5be561db.zip |
unzip: fix for .zip archives with >4GB file
function old new delta
unzip_main 2644 2665 +21
input_tab 926 927 +1
bb_banner 46 47 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 3/0 up/down: 23/0) Total: 23 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/unzip.c | 22 |
1 files changed, 20 insertions, 2 deletions
diff --git a/archival/unzip.c b/archival/unzip.c index d94bbabcf..12db4e579 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -82,11 +82,13 @@ enum { | |||
82 | ZIP_FILEHEADER_MAGIC = 0x504b0304, | 82 | ZIP_FILEHEADER_MAGIC = 0x504b0304, |
83 | ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */ | 83 | ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */ |
84 | ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */ | 84 | ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */ |
85 | ZIP64_CDE_MAGIC = 0x504b0606, /* End of Zip64 CDF */ | ||
85 | ZIP_DD_MAGIC = 0x504b0708, | 86 | ZIP_DD_MAGIC = 0x504b0708, |
86 | #else | 87 | #else |
87 | ZIP_FILEHEADER_MAGIC = 0x04034b50, | 88 | ZIP_FILEHEADER_MAGIC = 0x04034b50, |
88 | ZIP_CDF_MAGIC = 0x02014b50, | 89 | ZIP_CDF_MAGIC = 0x02014b50, |
89 | ZIP_CDE_MAGIC = 0x06054b50, | 90 | ZIP_CDE_MAGIC = 0x06054b50, |
91 | ZIP64_CDE_MAGIC = 0x06064b50, | ||
90 | ZIP_DD_MAGIC = 0x08074b50, | 92 | ZIP_DD_MAGIC = 0x08074b50, |
91 | #endif | 93 | #endif |
92 | }; | 94 | }; |
@@ -260,6 +262,12 @@ static uint32_t find_cdf_offset(void) | |||
260 | continue; | 262 | continue; |
261 | /* we found CDE! */ | 263 | /* we found CDE! */ |
262 | memcpy(cde.raw, p + 1, CDE_LEN); | 264 | memcpy(cde.raw, p + 1, CDE_LEN); |
265 | dbg("cde.this_disk_no:%d", cde.fmt.this_disk_no ); | ||
266 | dbg("cde.disk_with_cdf_no:%d", cde.fmt.disk_with_cdf_no ); | ||
267 | dbg("cde.cdf_entries_on_this_disk:%d", cde.fmt.cdf_entries_on_this_disk); | ||
268 | dbg("cde.cdf_entries_total:%d", cde.fmt.cdf_entries_total ); | ||
269 | dbg("cde.cdf_size:%d", cde.fmt.cdf_size ); | ||
270 | dbg("cde.cdf_offset:%x", cde.fmt.cdf_offset ); | ||
263 | FIX_ENDIANNESS_CDE(cde); | 271 | FIX_ENDIANNESS_CDE(cde); |
264 | /* | 272 | /* |
265 | * I've seen .ZIP files with seemingly valid CDEs | 273 | * I've seen .ZIP files with seemingly valid CDEs |
@@ -302,19 +310,27 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf) | |||
302 | dbg("got ZIP_CDE_MAGIC"); | 310 | dbg("got ZIP_CDE_MAGIC"); |
303 | return 0; /* EOF */ | 311 | return 0; /* EOF */ |
304 | } | 312 | } |
313 | if (magic == ZIP64_CDE_MAGIC) { /* seen in .zip with >4GB files */ | ||
314 | dbg("got ZIP64_CDE_MAGIC"); | ||
315 | return 0; /* EOF */ | ||
316 | } | ||
305 | xread(zip_fd, cdf->raw, CDF_HEADER_LEN); | 317 | xread(zip_fd, cdf->raw, CDF_HEADER_LEN); |
306 | 318 | ||
307 | FIX_ENDIANNESS_CDF(*cdf); | 319 | FIX_ENDIANNESS_CDF(*cdf); |
308 | dbg(" filename_len:%u extra_len:%u file_comment_length:%u", | 320 | dbg(" magic:%08x filename_len:%u extra_len:%u file_comment_length:%u", |
321 | magic, | ||
309 | (unsigned)cdf->fmt.filename_len, | 322 | (unsigned)cdf->fmt.filename_len, |
310 | (unsigned)cdf->fmt.extra_len, | 323 | (unsigned)cdf->fmt.extra_len, |
311 | (unsigned)cdf->fmt.file_comment_length | 324 | (unsigned)cdf->fmt.file_comment_length |
312 | ); | 325 | ); |
326 | //TODO: require that magic == ZIP_CDF_MAGIC? | ||
327 | |||
313 | cdf_offset += 4 + CDF_HEADER_LEN | 328 | cdf_offset += 4 + CDF_HEADER_LEN |
314 | + cdf->fmt.filename_len | 329 | + cdf->fmt.filename_len |
315 | + cdf->fmt.extra_len | 330 | + cdf->fmt.extra_len |
316 | + cdf->fmt.file_comment_length; | 331 | + cdf->fmt.file_comment_length; |
317 | 332 | ||
333 | dbg("Next cdf_offset 0x%x", cdf_offset); | ||
318 | return cdf_offset; | 334 | return cdf_offset; |
319 | }; | 335 | }; |
320 | #endif | 336 | #endif |
@@ -436,7 +452,9 @@ static void unzip_extract(zip_header_t *zip, int dst_fd) | |||
436 | } | 452 | } |
437 | 453 | ||
438 | /* Validate decompression - size */ | 454 | /* Validate decompression - size */ |
439 | if (zip->fmt.ucmpsize != xstate.bytes_out) { | 455 | if (zip->fmt.ucmpsize != 0xffffffff /* seen on files with >4GB uncompressed data */ |
456 | && zip->fmt.ucmpsize != xstate.bytes_out | ||
457 | ) { | ||
440 | /* Don't die. Who knows, maybe len calculation | 458 | /* Don't die. Who knows, maybe len calculation |
441 | * was botched somewhere. After all, crc matched! */ | 459 | * was botched somewhere. After all, crc matched! */ |
442 | bb_simple_error_msg("bad length"); | 460 | bb_simple_error_msg("bad length"); |