Fredrik Fornwall
9 years ago
2 changed files with 113 additions and 0 deletions
@ -0,0 +1,112 @@ |
|||
Backport of commit: |
|||
https://git.busybox.net/busybox/commit/?id=0ccf52a9fb9fa2f76eacbb6f1ef8419220557a40 |
|||
for issue: |
|||
https://bugs.busybox.net/show_bug.cgi?id=8821 |
|||
|
|||
diff --git a/archival/unzip.c b/archival/unzip.c
|
|||
index f41ab6f..b0a6ca8 100644
|
|||
--- a/archival/unzip.c
|
|||
+++ b/archival/unzip.c
|
|||
@@ -45,6 +45,12 @@
|
|||
#include "libbb.h" |
|||
#include "bb_archive.h" |
|||
|
|||
+#if 0
|
|||
+# define dbg(...) bb_error_msg(__VA_ARGS__)
|
|||
+#else
|
|||
+# define dbg(...) ((void)0)
|
|||
+#endif
|
|||
+
|
|||
enum { |
|||
#if BB_BIG_ENDIAN |
|||
ZIP_FILEHEADER_MAGIC = 0x504b0304, |
|||
@@ -193,15 +199,17 @@ static uint32_t find_cdf_offset(void)
|
|||
unsigned char *p; |
|||
off_t end; |
|||
unsigned char *buf = xzalloc(PEEK_FROM_END); |
|||
+ uint32_t found;
|
|||
|
|||
end = xlseek(zip_fd, 0, SEEK_END); |
|||
end -= PEEK_FROM_END; |
|||
if (end < 0) |
|||
end = 0; |
|||
- xlseek(zip_fd, end, SEEK_SET);
|
|||
+ dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end);
|
|||
+ xlseek(zip_fd, end, SEEK_SET);
|
|||
full_read(zip_fd, buf, PEEK_FROM_END); |
|||
|
|||
- cde_header.formatted.cdf_offset = BAD_CDF_OFFSET;
|
|||
+ found = BAD_CDF_OFFSET;
|
|||
p = buf; |
|||
while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { |
|||
if (*p != 'P') { |
|||
@@ -220,14 +228,25 @@ static uint32_t find_cdf_offset(void)
|
|||
/* |
|||
* I've seen .ZIP files with seemingly valid CDEs |
|||
* where cdf_offset points past EOF - ?? |
|||
- * Ignore such CDEs:
|
|||
+ * This check ignores such CDEs:
|
|||
*/ |
|||
- if (cde_header.formatted.cdf_offset < end + (p - buf))
|
|||
- break;
|
|||
- cde_header.formatted.cdf_offset = BAD_CDF_OFFSET;
|
|||
+ if (cde_header.formatted.cdf_offset < end + (p - buf)) {
|
|||
+ found = cde_header.formatted.cdf_offset;
|
|||
+ dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x",
|
|||
+ (unsigned)found, end + (p-3 - buf));
|
|||
+ dbg(" cdf_offset+cdf_size:0x%x",
|
|||
+ (unsigned)(found + SWAP_LE32(cde_header.formatted.cdf_size)));
|
|||
+ /*
|
|||
+ * We do not "break" here because only the last CDE is valid.
|
|||
+ * I've seen a .zip archive which contained a .zip file,
|
|||
+ * uncompressed, and taking the first CDE was using
|
|||
+ * the CDE inside that file!
|
|||
+ */
|
|||
+ }
|
|||
} |
|||
free(buf); |
|||
- return cde_header.formatted.cdf_offset;
|
|||
+ dbg("Found cdf_offset:0x%x", (unsigned)found);
|
|||
+ return found;
|
|||
}; |
|||
|
|||
static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) |
|||
@@ -240,9 +259,13 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
|
|||
cdf_offset = find_cdf_offset(); |
|||
|
|||
if (cdf_offset != BAD_CDF_OFFSET) { |
|||
+ dbg("Reading CDF at 0x%x", (unsigned)cdf_offset);
|
|||
xlseek(zip_fd, cdf_offset + 4, SEEK_SET); |
|||
xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); |
|||
FIX_ENDIANNESS_CDF(*cdf_ptr); |
|||
+ dbg("file_name_length:%u", (unsigned)cdf_ptr->formatted.file_name_length);
|
|||
+ dbg("extra_field_length:%u", (unsigned)cdf_ptr->formatted.extra_field_length);
|
|||
+ dbg("file_comment_length:%u", (unsigned)cdf_ptr->formatted.file_comment_length);
|
|||
cdf_offset += 4 + CDF_HEADER_LEN |
|||
+ cdf_ptr->formatted.file_name_length |
|||
+ cdf_ptr->formatted.extra_field_length |
|||
@@ -532,11 +555,14 @@ int unzip_main(int argc, char **argv)
|
|||
/* Check magic number */ |
|||
xread(zip_fd, &magic, 4); |
|||
/* Central directory? It's at the end, so exit */ |
|||
- if (magic == ZIP_CDF_MAGIC)
|
|||
+ if (magic == ZIP_CDF_MAGIC) {
|
|||
+ dbg("got ZIP_CDF_MAGIC");
|
|||
break; |
|||
+ }
|
|||
#if ENABLE_DESKTOP |
|||
/* Data descriptor? It was a streaming file, go on */ |
|||
if (magic == ZIP_DD_MAGIC) { |
|||
+ dbg("got ZIP_DD_MAGIC");
|
|||
/* skip over duplicate crc32, cmpsize and ucmpsize */ |
|||
unzip_skip(3 * 4); |
|||
continue; |
|||
@@ -544,6 +570,7 @@ int unzip_main(int argc, char **argv)
|
|||
#endif |
|||
if (magic != ZIP_FILEHEADER_MAGIC) |
|||
bb_error_msg_and_die("invalid zip magic %08X", (int)magic); |
|||
+ dbg("got ZIP_FILEHEADER_MAGIC");
|
|||
|
|||
/* Read the file header */ |
|||
xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); |
|||
|
Loading…
Reference in new issue