diff options
author | Denys Vlasenko | 2021-04-14 21:15:25 +0200 |
---|---|---|
committer | Denys Vlasenko | 2021-04-14 21:15:25 +0200 |
commit | afc766fc12d54670aaed9bbb228efc7a5be561db (patch) | |
tree | 6c3416536a992b40982924099831cb54091cee3a | |
parent | 1a45b2ccea94b0fc123798f276a0801413597880 (diff) | |
download | busybox-afc766fc12d54670aaed9bbb228efc7a5be561db.zip busybox-afc766fc12d54670aaed9bbb228efc7a5be561db.tar.gz |
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 d94bbab..12db4e5 100644 --- a/archival/unzip.c +++ b/archival/unzip.c @@ -82,11 +82,13 @@ enum { ZIP_FILEHEADER_MAGIC = 0x504b0304, ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */ ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */ + ZIP64_CDE_MAGIC = 0x504b0606, /* End of Zip64 CDF */ ZIP_DD_MAGIC = 0x504b0708, #else ZIP_FILEHEADER_MAGIC = 0x04034b50, ZIP_CDF_MAGIC = 0x02014b50, ZIP_CDE_MAGIC = 0x06054b50, + ZIP64_CDE_MAGIC = 0x06064b50, ZIP_DD_MAGIC = 0x08074b50, #endif }; @@ -260,6 +262,12 @@ static uint32_t find_cdf_offset(void) continue; /* we found CDE! */ memcpy(cde.raw, p + 1, CDE_LEN); + dbg("cde.this_disk_no:%d", cde.fmt.this_disk_no ); + dbg("cde.disk_with_cdf_no:%d", cde.fmt.disk_with_cdf_no ); + dbg("cde.cdf_entries_on_this_disk:%d", cde.fmt.cdf_entries_on_this_disk); + dbg("cde.cdf_entries_total:%d", cde.fmt.cdf_entries_total ); + dbg("cde.cdf_size:%d", cde.fmt.cdf_size ); + dbg("cde.cdf_offset:%x", cde.fmt.cdf_offset ); FIX_ENDIANNESS_CDE(cde); /* * 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) dbg("got ZIP_CDE_MAGIC"); return 0; /* EOF */ } + if (magic == ZIP64_CDE_MAGIC) { /* seen in .zip with >4GB files */ + dbg("got ZIP64_CDE_MAGIC"); + return 0; /* EOF */ + } xread(zip_fd, cdf->raw, CDF_HEADER_LEN); FIX_ENDIANNESS_CDF(*cdf); - dbg(" filename_len:%u extra_len:%u file_comment_length:%u", + dbg(" magic:%08x filename_len:%u extra_len:%u file_comment_length:%u", + magic, (unsigned)cdf->fmt.filename_len, (unsigned)cdf->fmt.extra_len, (unsigned)cdf->fmt.file_comment_length ); +//TODO: require that magic == ZIP_CDF_MAGIC? + cdf_offset += 4 + CDF_HEADER_LEN + cdf->fmt.filename_len + cdf->fmt.extra_len + cdf->fmt.file_comment_length; + dbg("Next cdf_offset 0x%x", cdf_offset); return cdf_offset; }; #endif @@ -436,7 +452,9 @@ static void unzip_extract(zip_header_t *zip, int dst_fd) } /* Validate decompression - size */ - if (zip->fmt.ucmpsize != xstate.bytes_out) { + if (zip->fmt.ucmpsize != 0xffffffff /* seen on files with >4GB uncompressed data */ + && zip->fmt.ucmpsize != xstate.bytes_out + ) { /* Don't die. Who knows, maybe len calculation * was botched somewhere. After all, crc matched! */ bb_simple_error_msg("bad length"); |