aboutsummaryrefslogtreecommitdiff
path: root/archival
diff options
context:
space:
mode:
Diffstat (limited to 'archival')
-rw-r--r--archival/libarchive/decompress_gunzip.c11
-rw-r--r--archival/unzip.c34
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)
223static void huft_free(huft_t *p) 225static 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)
294static huft_t* huft_build(const unsigned *b, const unsigned n, 301static 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? */