chiark / gitweb /
1b587a082a67ca011e7833b774271afbd32f6e8f
[termux-packages] / packages / busybox / unzip.c.patch
1 Backport of commit:
2   https://git.busybox.net/busybox/commit/?id=0ccf52a9fb9fa2f76eacbb6f1ef8419220557a40
3 for issue:
4   https://bugs.busybox.net/show_bug.cgi?id=8821
5
6 diff --git a/archival/unzip.c b/archival/unzip.c
7 index f41ab6f..b0a6ca8 100644
8 --- a/archival/unzip.c
9 +++ b/archival/unzip.c
10 @@ -45,6 +45,12 @@
11  #include "libbb.h"
12  #include "bb_archive.h"
13  
14 +#if 0
15 +# define dbg(...) bb_error_msg(__VA_ARGS__)
16 +#else
17 +# define dbg(...) ((void)0)
18 +#endif
19 +
20  enum {
21  #if BB_BIG_ENDIAN
22         ZIP_FILEHEADER_MAGIC = 0x504b0304,
23 @@ -193,15 +199,17 @@ static uint32_t find_cdf_offset(void)
24         unsigned char *p;
25         off_t end;
26         unsigned char *buf = xzalloc(PEEK_FROM_END);
27 +       uint32_t found;
28  
29         end = xlseek(zip_fd, 0, SEEK_END);
30         end -= PEEK_FROM_END;
31         if (end < 0)
32                 end = 0;
33 -       xlseek(zip_fd, end, SEEK_SET);
34 +       dbg("Looking for cdf_offset starting from 0x%"OFF_FMT"x", end);
35 +       xlseek(zip_fd, end, SEEK_SET);
36         full_read(zip_fd, buf, PEEK_FROM_END);
37  
38 -       cde_header.formatted.cdf_offset = BAD_CDF_OFFSET;
39 +       found = BAD_CDF_OFFSET;
40         p = buf;
41         while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) {
42                 if (*p != 'P') {
43 @@ -220,14 +228,25 @@ static uint32_t find_cdf_offset(void)
44                 /*
45                  * I've seen .ZIP files with seemingly valid CDEs
46                  * where cdf_offset points past EOF - ??
47 -                * Ignore such CDEs:
48 +                * This check ignores such CDEs:
49                  */
50 -               if (cde_header.formatted.cdf_offset < end + (p - buf))
51 -                       break;
52 -               cde_header.formatted.cdf_offset = BAD_CDF_OFFSET;
53 +               if (cde_header.formatted.cdf_offset < end + (p - buf)) {
54 +                       found = cde_header.formatted.cdf_offset;
55 +                       dbg("Possible cdf_offset:0x%x at 0x%"OFF_FMT"x",
56 +                               (unsigned)found, end + (p-3 - buf));
57 +                       dbg("  cdf_offset+cdf_size:0x%x",
58 +                               (unsigned)(found + SWAP_LE32(cde_header.formatted.cdf_size)));
59 +                       /*
60 +                        * We do not "break" here because only the last CDE is valid.
61 +                        * I've seen a .zip archive which contained a .zip file,
62 +                        * uncompressed, and taking the first CDE was using
63 +                        * the CDE inside that file!
64 +                        */
65 +               }
66         }
67         free(buf);
68 -       return cde_header.formatted.cdf_offset;
69 +       dbg("Found cdf_offset:0x%x", (unsigned)found);
70 +       return found;
71  };
72  
73  static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
74 @@ -240,9 +259,13 @@ static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr)
75                 cdf_offset = find_cdf_offset();
76  
77         if (cdf_offset != BAD_CDF_OFFSET) {
78 +               dbg("Reading CDF at 0x%x", (unsigned)cdf_offset);
79                 xlseek(zip_fd, cdf_offset + 4, SEEK_SET);
80                 xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN);
81                 FIX_ENDIANNESS_CDF(*cdf_ptr);
82 +               dbg("file_name_length:%u", (unsigned)cdf_ptr->formatted.file_name_length);
83 +               dbg("extra_field_length:%u", (unsigned)cdf_ptr->formatted.extra_field_length);
84 +               dbg("file_comment_length:%u", (unsigned)cdf_ptr->formatted.file_comment_length);
85                 cdf_offset += 4 + CDF_HEADER_LEN
86                         + cdf_ptr->formatted.file_name_length
87                         + cdf_ptr->formatted.extra_field_length
88 @@ -532,11 +555,14 @@ int unzip_main(int argc, char **argv)
89                 /* Check magic number */
90                 xread(zip_fd, &magic, 4);
91                 /* Central directory? It's at the end, so exit */
92 -               if (magic == ZIP_CDF_MAGIC)
93 +               if (magic == ZIP_CDF_MAGIC) {
94 +                       dbg("got ZIP_CDF_MAGIC");
95                         break;
96 +               }
97  #if ENABLE_DESKTOP
98                 /* Data descriptor? It was a streaming file, go on */
99                 if (magic == ZIP_DD_MAGIC) {
100 +                       dbg("got ZIP_DD_MAGIC");
101                         /* skip over duplicate crc32, cmpsize and ucmpsize */
102                         unzip_skip(3 * 4);
103                         continue;
104 @@ -544,6 +570,7 @@ int unzip_main(int argc, char **argv)
105  #endif
106                 if (magic != ZIP_FILEHEADER_MAGIC)
107                         bb_error_msg_and_die("invalid zip magic %08X", (int)magic);
108 +               dbg("got ZIP_FILEHEADER_MAGIC");
109  
110                 /* Read the file header */
111                 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN);
112