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>
This commit is contained in:
parent
1a45b2ccea
commit
afc766fc12
@ -82,11 +82,13 @@ enum {
|
|||||||
ZIP_FILEHEADER_MAGIC = 0x504b0304,
|
ZIP_FILEHEADER_MAGIC = 0x504b0304,
|
||||||
ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */
|
ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */
|
||||||
ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */
|
ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */
|
||||||
|
ZIP64_CDE_MAGIC = 0x504b0606, /* End of Zip64 CDF */
|
||||||
ZIP_DD_MAGIC = 0x504b0708,
|
ZIP_DD_MAGIC = 0x504b0708,
|
||||||
#else
|
#else
|
||||||
ZIP_FILEHEADER_MAGIC = 0x04034b50,
|
ZIP_FILEHEADER_MAGIC = 0x04034b50,
|
||||||
ZIP_CDF_MAGIC = 0x02014b50,
|
ZIP_CDF_MAGIC = 0x02014b50,
|
||||||
ZIP_CDE_MAGIC = 0x06054b50,
|
ZIP_CDE_MAGIC = 0x06054b50,
|
||||||
|
ZIP64_CDE_MAGIC = 0x06064b50,
|
||||||
ZIP_DD_MAGIC = 0x08074b50,
|
ZIP_DD_MAGIC = 0x08074b50,
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@ -260,6 +262,12 @@ static uint32_t find_cdf_offset(void)
|
|||||||
continue;
|
continue;
|
||||||
/* we found CDE! */
|
/* we found CDE! */
|
||||||
memcpy(cde.raw, p + 1, CDE_LEN);
|
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);
|
FIX_ENDIANNESS_CDE(cde);
|
||||||
/*
|
/*
|
||||||
* I've seen .ZIP files with seemingly valid CDEs
|
* 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");
|
dbg("got ZIP_CDE_MAGIC");
|
||||||
return 0; /* EOF */
|
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);
|
xread(zip_fd, cdf->raw, CDF_HEADER_LEN);
|
||||||
|
|
||||||
FIX_ENDIANNESS_CDF(*cdf);
|
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.filename_len,
|
||||||
(unsigned)cdf->fmt.extra_len,
|
(unsigned)cdf->fmt.extra_len,
|
||||||
(unsigned)cdf->fmt.file_comment_length
|
(unsigned)cdf->fmt.file_comment_length
|
||||||
);
|
);
|
||||||
|
//TODO: require that magic == ZIP_CDF_MAGIC?
|
||||||
|
|
||||||
cdf_offset += 4 + CDF_HEADER_LEN
|
cdf_offset += 4 + CDF_HEADER_LEN
|
||||||
+ cdf->fmt.filename_len
|
+ cdf->fmt.filename_len
|
||||||
+ cdf->fmt.extra_len
|
+ cdf->fmt.extra_len
|
||||||
+ cdf->fmt.file_comment_length;
|
+ cdf->fmt.file_comment_length;
|
||||||
|
|
||||||
|
dbg("Next cdf_offset 0x%x", cdf_offset);
|
||||||
return cdf_offset;
|
return cdf_offset;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@ -436,7 +452,9 @@ static void unzip_extract(zip_header_t *zip, int dst_fd)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Validate decompression - size */
|
/* 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
|
/* Don't die. Who knows, maybe len calculation
|
||||||
* was botched somewhere. After all, crc matched! */
|
* was botched somewhere. After all, crc matched! */
|
||||||
bb_simple_error_msg("bad length");
|
bb_simple_error_msg("bad length");
|
||||||
|
Loading…
Reference in New Issue
Block a user