diff options
Diffstat (limited to 'archival')
-rw-r--r-- | archival/libarchive/decompress_gunzip.c | 11 | ||||
-rw-r--r-- | archival/unzip.c | 34 |
2 files changed, 38 insertions, 7 deletions
diff --git a/archival/libarchive/decompress_gunzip.c b/archival/libarchive/decompress_gunzip.c index b2a3eb1c2..d2f7a9309 100644 --- a/archival/libarchive/decompress_gunzip.c +++ b/archival/libarchive/decompress_gunzip.c | |||
@@ -220,10 +220,19 @@ static const uint8_t border[] ALIGN1 = { | |||
220 | * each table. | 220 | * each table. |
221 | * t: table to free | 221 | * t: table to free |
222 | */ | 222 | */ |
223 | #define BAD_HUFT(p) ((uintptr_t)(p) & 1) | ||
224 | #define ERR_RET ((huft_t*)(uintptr_t)1) | ||
223 | static void huft_free(huft_t *p) | 225 | static void huft_free(huft_t *p) |
224 | { | 226 | { |
225 | huft_t *q; | 227 | huft_t *q; |
226 | 228 | ||
229 | /* | ||
230 | * If 'p' has the error bit set we have to clear it, otherwise we might run | ||
231 | * into a segmentation fault or an invalid pointer to free(p) | ||
232 | */ | ||
233 | //if (BAD_HUFT(p)) // commented out, since bit clearing has effect only if condition is true | ||
234 | p = (huft_t*)((uintptr_t)p & ~(uintptr_t)ERR_RET); | ||
235 | |||
227 | /* Go through linked list, freeing from the malloced (t[-1]) address. */ | 236 | /* Go through linked list, freeing from the malloced (t[-1]) address. */ |
228 | while (p) { | 237 | while (p) { |
229 | q = (--p)->v.t; | 238 | q = (--p)->v.t; |
@@ -289,8 +298,6 @@ static unsigned fill_bitbuffer(STATE_PARAM unsigned bitbuffer, unsigned *current | |||
289 | * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table | 298 | * or a valid pointer to a Huffman table, ORed with 0x1 if incompete table |
290 | * is given: "fixed inflate" decoder feeds us such data. | 299 | * is given: "fixed inflate" decoder feeds us such data. |
291 | */ | 300 | */ |
292 | #define BAD_HUFT(p) ((uintptr_t)(p) & 1) | ||
293 | #define ERR_RET ((huft_t*)(uintptr_t)1) | ||
294 | static huft_t* huft_build(const unsigned *b, const unsigned n, | 301 | static huft_t* huft_build(const unsigned *b, const unsigned n, |
295 | const unsigned s, const struct cp_ext *cp_ext, | 302 | const unsigned s, const struct cp_ext *cp_ext, |
296 | unsigned *m) | 303 | unsigned *m) |
diff --git a/archival/unzip.c b/archival/unzip.c index 19353c708..e02cf33e3 100644 --- a/archival/unzip.c +++ b/archival/unzip.c | |||
@@ -64,6 +64,7 @@ | |||
64 | //usage: "\n -o Overwrite" | 64 | //usage: "\n -o Overwrite" |
65 | //usage: "\n -j Do not restore paths" | 65 | //usage: "\n -j Do not restore paths" |
66 | //usage: "\n -p Print to stdout" | 66 | //usage: "\n -p Print to stdout" |
67 | //usage: "\n -t Test" | ||
67 | //usage: "\n -q Quiet" | 68 | //usage: "\n -q Quiet" |
68 | //usage: "\n -x FILE Exclude FILEs" | 69 | //usage: "\n -x FILE Exclude FILEs" |
69 | //usage: "\n -d DIR Extract into DIR" | 70 | //usage: "\n -d DIR Extract into DIR" |
@@ -85,11 +86,13 @@ enum { | |||
85 | ZIP_FILEHEADER_MAGIC = 0x504b0304, | 86 | ZIP_FILEHEADER_MAGIC = 0x504b0304, |
86 | ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */ | 87 | ZIP_CDF_MAGIC = 0x504b0102, /* CDF item */ |
87 | ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */ | 88 | ZIP_CDE_MAGIC = 0x504b0506, /* End of CDF */ |
89 | ZIP64_CDE_MAGIC = 0x504b0606, /* End of Zip64 CDF */ | ||
88 | ZIP_DD_MAGIC = 0x504b0708, | 90 | ZIP_DD_MAGIC = 0x504b0708, |
89 | #else | 91 | #else |
90 | ZIP_FILEHEADER_MAGIC = 0x04034b50, | 92 | ZIP_FILEHEADER_MAGIC = 0x04034b50, |
91 | ZIP_CDF_MAGIC = 0x02014b50, | 93 | ZIP_CDF_MAGIC = 0x02014b50, |
92 | ZIP_CDE_MAGIC = 0x06054b50, | 94 | ZIP_CDE_MAGIC = 0x06054b50, |
95 | ZIP64_CDE_MAGIC = 0x06064b50, | ||
93 | ZIP_DD_MAGIC = 0x08074b50, | 96 | ZIP_DD_MAGIC = 0x08074b50, |
94 | #endif | 97 | #endif |
95 | }; | 98 | }; |
@@ -263,6 +266,12 @@ static uint32_t find_cdf_offset(void) | |||
263 | continue; | 266 | continue; |
264 | /* we found CDE! */ | 267 | /* we found CDE! */ |
265 | memcpy(cde.raw, p + 1, CDE_LEN); | 268 | memcpy(cde.raw, p + 1, CDE_LEN); |
269 | dbg("cde.this_disk_no:%d", cde.fmt.this_disk_no ); | ||
270 | dbg("cde.disk_with_cdf_no:%d", cde.fmt.disk_with_cdf_no ); | ||
271 | dbg("cde.cdf_entries_on_this_disk:%d", cde.fmt.cdf_entries_on_this_disk); | ||
272 | dbg("cde.cdf_entries_total:%d", cde.fmt.cdf_entries_total ); | ||
273 | dbg("cde.cdf_size:%d", cde.fmt.cdf_size ); | ||
274 | dbg("cde.cdf_offset:%x", cde.fmt.cdf_offset ); | ||
266 | FIX_ENDIANNESS_CDE(cde); | 275 | FIX_ENDIANNESS_CDE(cde); |
267 | /* | 276 | /* |
268 | * I've seen .ZIP files with seemingly valid CDEs | 277 | * I've seen .ZIP files with seemingly valid CDEs |
@@ -305,19 +314,27 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf) | |||
305 | dbg("got ZIP_CDE_MAGIC"); | 314 | dbg("got ZIP_CDE_MAGIC"); |
306 | return 0; /* EOF */ | 315 | return 0; /* EOF */ |
307 | } | 316 | } |
317 | if (magic == ZIP64_CDE_MAGIC) { /* seen in .zip with >4GB files */ | ||
318 | dbg("got ZIP64_CDE_MAGIC"); | ||
319 | return 0; /* EOF */ | ||
320 | } | ||
308 | xread(zip_fd, cdf->raw, CDF_HEADER_LEN); | 321 | xread(zip_fd, cdf->raw, CDF_HEADER_LEN); |
309 | 322 | ||
310 | FIX_ENDIANNESS_CDF(*cdf); | 323 | FIX_ENDIANNESS_CDF(*cdf); |
311 | dbg(" filename_len:%u extra_len:%u file_comment_length:%u", | 324 | dbg(" magic:%08x filename_len:%u extra_len:%u file_comment_length:%u", |
325 | magic, | ||
312 | (unsigned)cdf->fmt.filename_len, | 326 | (unsigned)cdf->fmt.filename_len, |
313 | (unsigned)cdf->fmt.extra_len, | 327 | (unsigned)cdf->fmt.extra_len, |
314 | (unsigned)cdf->fmt.file_comment_length | 328 | (unsigned)cdf->fmt.file_comment_length |
315 | ); | 329 | ); |
330 | //TODO: require that magic == ZIP_CDF_MAGIC? | ||
331 | |||
316 | cdf_offset += 4 + CDF_HEADER_LEN | 332 | cdf_offset += 4 + CDF_HEADER_LEN |
317 | + cdf->fmt.filename_len | 333 | + cdf->fmt.filename_len |
318 | + cdf->fmt.extra_len | 334 | + cdf->fmt.extra_len |
319 | + cdf->fmt.file_comment_length; | 335 | + cdf->fmt.file_comment_length; |
320 | 336 | ||
337 | dbg("Next cdf_offset 0x%x", cdf_offset); | ||
321 | return cdf_offset; | 338 | return cdf_offset; |
322 | }; | 339 | }; |
323 | #endif | 340 | #endif |
@@ -439,7 +456,9 @@ static void unzip_extract(zip_header_t *zip, int dst_fd) | |||
439 | } | 456 | } |
440 | 457 | ||
441 | /* Validate decompression - size */ | 458 | /* Validate decompression - size */ |
442 | if (zip->fmt.ucmpsize != xstate.bytes_out) { | 459 | if (zip->fmt.ucmpsize != 0xffffffff /* seen on files with >4GB uncompressed data */ |
460 | && zip->fmt.ucmpsize != xstate.bytes_out | ||
461 | ) { | ||
443 | /* Don't die. Who knows, maybe len calculation | 462 | /* Don't die. Who knows, maybe len calculation |
444 | * was botched somewhere. After all, crc matched! */ | 463 | * was botched somewhere. After all, crc matched! */ |
445 | bb_simple_error_msg("bad length"); | 464 | bb_simple_error_msg("bad length"); |
@@ -541,7 +560,7 @@ int unzip_main(int argc, char **argv) | |||
541 | 560 | ||
542 | opts = 0; | 561 | opts = 0; |
543 | /* '-' makes getopt return 1 for non-options */ | 562 | /* '-' makes getopt return 1 for non-options */ |
544 | while ((i = getopt(argc, argv, "-d:lnopqxjv")) != -1) { | 563 | while ((i = getopt(argc, argv, "-d:lnotpqxjv")) != -1) { |
545 | switch (i) { | 564 | switch (i) { |
546 | case 'd': /* Extract to base directory */ | 565 | case 'd': /* Extract to base directory */ |
547 | base_dir = optarg; | 566 | base_dir = optarg; |
@@ -559,8 +578,13 @@ int unzip_main(int argc, char **argv) | |||
559 | overwrite = O_ALWAYS; | 578 | overwrite = O_ALWAYS; |
560 | break; | 579 | break; |
561 | 580 | ||
562 | case 'p': /* Extract files to stdout and fall through to set verbosity */ | 581 | case 't': /* Extract files to /dev/null */ |
582 | xmove_fd(xopen("/dev/null", O_WRONLY), STDOUT_FILENO); | ||
583 | /*fallthrough*/ | ||
584 | |||
585 | case 'p': /* Extract files to stdout */ | ||
563 | dst_fd = STDOUT_FILENO; | 586 | dst_fd = STDOUT_FILENO; |
587 | /*fallthrough*/ | ||
564 | 588 | ||
565 | case 'q': /* Be quiet */ | 589 | case 'q': /* Be quiet */ |
566 | quiet++; | 590 | quiet++; |
@@ -969,7 +993,6 @@ int unzip_main(int argc, char **argv) | |||
969 | /* O_NOFOLLOW defends against symlink attacks */ | 993 | /* O_NOFOLLOW defends against symlink attacks */ |
970 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW); | 994 | dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC | O_NOFOLLOW); |
971 | #endif | 995 | #endif |
972 | do_extract: | ||
973 | if (!quiet) { | 996 | if (!quiet) { |
974 | printf(/* zip.fmt.method == 0 | 997 | printf(/* zip.fmt.method == 0 |
975 | ? " extracting: %s\n" | 998 | ? " extracting: %s\n" |
@@ -977,6 +1000,7 @@ int unzip_main(int argc, char **argv) | |||
977 | printable_string(dst_fn) | 1000 | printable_string(dst_fn) |
978 | ); | 1001 | ); |
979 | } | 1002 | } |
1003 | do_extract: | ||
980 | #if ENABLE_FEATURE_UNZIP_CDF | 1004 | #if ENABLE_FEATURE_UNZIP_CDF |
981 | if (S_ISLNK(file_mode)) { | 1005 | if (S_ISLNK(file_mode)) { |
982 | if (dst_fd != STDOUT_FILENO) /* not -p? */ | 1006 | if (dst_fd != STDOUT_FILENO) /* not -p? */ |