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"); |
