unzip: fix for .zip archives with >4GB file
No binary (build failed)
—
(log yok)
| @@ -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"); | |