1 #include "miniz.h"
2 
3 /**************************************************************************
4  *
5  * Copyright 2013-2014 RAD Game Tools and Valve Software
6  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
7  * All Rights Reserved.
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  *
27  **************************************************************************/
28 
29 typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
30 typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
31 typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
32 
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36 
37 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
38 /* Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ */
39 #if 0
40     static mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
41     {
42         static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
43                                                0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
44         mz_uint32 crcu32 = (mz_uint32)crc;
45         if (!ptr)
46             return MZ_CRC32_INIT;
47         crcu32 = ~crcu32;
48         while (buf_len--)
49         {
50             mz_uint8 b = *ptr++;
51             crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
52             crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
53         }
54         return ~crcu32;
55     }
56 #elif defined(USE_EXTERNAL_MZCRC)
57 /* If USE_EXTERNAL_CRC is defined, an external module will export the
58  * mz_crc32() symbol for us to use, e.g. an SSE-accelerated version.
59  * Depending on the impl, it may be necessary to ~ the input/output crc values.
60  */
61 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len);
62 #else
63 /* Faster, but larger CPU cache footprint.
64  */
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)65 static mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
66 {
67     static const mz_uint32 s_crc_table[256] =
68         {
69           0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
70           0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
71           0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
72           0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
73           0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
74           0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
75           0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
76           0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
77           0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
78           0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
79           0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
80           0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
81           0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
82           0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
83           0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
84           0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
85           0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
86           0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
87           0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
88           0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
89           0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
90           0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
91           0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
92           0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
93           0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
94           0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
95           0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
96           0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
97           0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
98           0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
99           0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
100           0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
101           0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
102           0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
103           0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
104           0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
105           0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
106         };
107 
108     mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
109     const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
110 
111     while (buf_len >= 4)
112     {
113         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
114         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
115         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
116         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
117         pByte_buf += 4;
118         buf_len -= 4;
119     }
120 
121     while (buf_len)
122     {
123         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
124         ++pByte_buf;
125         --buf_len;
126     }
127 
128     return ~crc32;
129 }
130 #endif
131 #endif /* MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS */
132 
miniz_def_alloc_func(void * opaque,size_t items,size_t size)133 static /*MINIZ_EXPORT*/ void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
134 {
135     (void)opaque, (void)items, (void)size;
136     return MZ_MALLOC(items * size);
137 }
miniz_def_free_func(void * opaque,void * address)138 static /*MINIZ_EXPORT*/ void miniz_def_free_func(void *opaque, void *address)
139 {
140     (void)opaque, (void)address;
141     MZ_FREE(address);
142 }
miniz_def_realloc_func(void * opaque,void * address,size_t items,size_t size)143 static /*MINIZ_EXPORT*/ void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
144 {
145     (void)opaque, (void)address, (void)items, (void)size;
146     return MZ_REALLOC(address, items * size);
147 }
148 
149 #ifdef __cplusplus
150 }
151 #endif
152 
153 /*
154   This is free and unencumbered software released into the public domain.
155 
156   Anyone is free to copy, modify, publish, use, compile, sell, or
157   distribute this software, either in source code form or as a compiled
158   binary, for any purpose, commercial or non-commercial, and by any
159   means.
160 
161   In jurisdictions that recognize copyright laws, the author or authors
162   of this software dedicate any and all copyright interest in the
163   software to the public domain. We make this dedication for the benefit
164   of the public at large and to the detriment of our heirs and
165   successors. We intend this dedication to be an overt act of
166   relinquishment in perpetuity of all present and future rights to this
167   software under copyright law.
168 
169   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
170   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
171   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
172   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
173   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
174   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
175   OTHER DEALINGS IN THE SOFTWARE.
176 
177   For more information, please refer to <http://unlicense.org/>
178 */
179 
180 #ifndef MINIZ_NO_INFLATE_APIS
181 
182 #ifdef __cplusplus
183 extern "C" {
184 #endif
185 
186 /* ------------------- Low-level Decompression (completely independent from all compression API's) */
187 
188 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
189 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
190 
191 #define TINFL_CR_BEGIN  \
192     switch (r->m_state) \
193     {                   \
194         case 0:
195 #define TINFL_CR_RETURN(state_index, result) \
196     do                                       \
197     {                                        \
198         status = result;                     \
199         r->m_state = state_index;            \
200         goto common_exit;                    \
201         case state_index:;                   \
202     }                                        \
203     MZ_MACRO_END
204 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
205     do                                               \
206     {                                                \
207         for (;;)                                     \
208         {                                            \
209             TINFL_CR_RETURN(state_index, result);    \
210         }                                            \
211     }                                                \
212     MZ_MACRO_END
213 #define TINFL_CR_FINISH }
214 
215 #define TINFL_GET_BYTE(state_index, c)                                                                                                                           \
216     do                                                                                                                                                           \
217     {                                                                                                                                                            \
218         while (pIn_buf_cur >= pIn_buf_end)                                                                                                                       \
219         {                                                                                                                                                        \
220             TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
221         }                                                                                                                                                        \
222         c = *pIn_buf_cur++;                                                                                                                                      \
223     }                                                                                                                                                            \
224     MZ_MACRO_END
225 
226 #define TINFL_NEED_BITS(state_index, n)                \
227     do                                                 \
228     {                                                  \
229         mz_uint c;                                     \
230         TINFL_GET_BYTE(state_index, c);                \
231         bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
232         num_bits += 8;                                 \
233     } while (num_bits < (mz_uint)(n))
234 #define TINFL_SKIP_BITS(state_index, n)      \
235     do                                       \
236     {                                        \
237         if (num_bits < (mz_uint)(n))         \
238         {                                    \
239             TINFL_NEED_BITS(state_index, n); \
240         }                                    \
241         bit_buf >>= (n);                     \
242         num_bits -= (n);                     \
243     }                                        \
244     MZ_MACRO_END
245 #define TINFL_GET_BITS(state_index, b, n)    \
246     do                                       \
247     {                                        \
248         if (num_bits < (mz_uint)(n))         \
249         {                                    \
250             TINFL_NEED_BITS(state_index, n); \
251         }                                    \
252         b = bit_buf & ((1 << (n)) - 1);      \
253         bit_buf >>= (n);                     \
254         num_bits -= (n);                     \
255     }                                        \
256     MZ_MACRO_END
257 
258 /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
259 /* It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a */
260 /* Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the */
261 /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
262 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \
263     do                                                                         \
264     {                                                                          \
265         temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];     \
266         if (temp >= 0)                                                         \
267         {                                                                      \
268             code_len = temp >> 9;                                              \
269             if ((code_len) && (num_bits >= code_len))                          \
270                 break;                                                         \
271         }                                                                      \
272         else if (num_bits > TINFL_FAST_LOOKUP_BITS)                            \
273         {                                                                      \
274             code_len = TINFL_FAST_LOOKUP_BITS;                                 \
275             do                                                                 \
276             {                                                                  \
277                 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
278             } while ((temp < 0) && (num_bits >= (code_len + 1)));              \
279             if (temp >= 0)                                                     \
280                 break;                                                         \
281         }                                                                      \
282         TINFL_GET_BYTE(state_index, c);                                        \
283         bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                         \
284         num_bits += 8;                                                         \
285     } while (num_bits < 15);
286 
287 /* TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read */
288 /* beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully */
289 /* decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. */
290 /* The slow path is only executed at the very end of the input buffer. */
291 /* v1.16: The original macro handled the case at the very end of the passed-in input buffer, but we also need to handle the case where the user passes in 1+zillion bytes */
292 /* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
293 #define TINFL_HUFF_DECODE(state_index, sym, pHuff)                                                                                  \
294     do                                                                                                                              \
295     {                                                                                                                               \
296         int temp;                                                                                                                   \
297         mz_uint code_len, c;                                                                                                        \
298         if (num_bits < 15)                                                                                                          \
299         {                                                                                                                           \
300             if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \
301             {                                                                                                                       \
302                 TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                                                                         \
303             }                                                                                                                       \
304             else                                                                                                                    \
305             {                                                                                                                       \
306                 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
307                 pIn_buf_cur += 2;                                                                                                   \
308                 num_bits += 16;                                                                                                     \
309             }                                                                                                                       \
310         }                                                                                                                           \
311         if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                               \
312             code_len = temp >> 9, temp &= 511;                                                                                      \
313         else                                                                                                                        \
314         {                                                                                                                           \
315             code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \
316             do                                                                                                                      \
317             {                                                                                                                       \
318                 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];                                                      \
319             } while (temp < 0);                                                                                                     \
320         }                                                                                                                           \
321         sym = temp;                                                                                                                 \
322         bit_buf >>= code_len;                                                                                                       \
323         num_bits -= code_len;                                                                                                       \
324     }                                                                                                                               \
325     MZ_MACRO_END
326 
tinfl_decompress(tinfl_decompressor * r,const mz_uint8 * pIn_buf_next,size_t * pIn_buf_size,mz_uint8 * pOut_buf_start,mz_uint8 * pOut_buf_next,size_t * pOut_buf_size,const mz_uint32 decomp_flags)327 tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags)
328 {
329     static const int s_length_base[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 };
330     static const int s_length_extra[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0 };
331     static const int s_dist_base[32] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 0, 0 };
332     static const int s_dist_extra[32] = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13 };
333     static const mz_uint8 s_length_dezigzag[19] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
334     static const int s_min_table_sizes[3] = { 257, 1, 4 };
335 
336     tinfl_status status = TINFL_STATUS_FAILED;
337     mz_uint32 num_bits, dist, counter, num_extra;
338     tinfl_bit_buf_t bit_buf;
339     const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
340     mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
341     size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start;
342 
343     /* Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). */
344     if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
345     {
346         *pIn_buf_size = *pOut_buf_size = 0;
347         return TINFL_STATUS_BAD_PARAM;
348     }
349 
350     num_bits = r->m_num_bits;
351     bit_buf = r->m_bit_buf;
352     dist = r->m_dist;
353     counter = r->m_counter;
354     num_extra = r->m_num_extra;
355     dist_from_out_buf_start = r->m_dist_from_out_buf_start;
356     TINFL_CR_BEGIN
357 
358     bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
359     r->m_z_adler32 = r->m_check_adler32 = 1;
360     if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
361     {
362         TINFL_GET_BYTE(1, r->m_zhdr0);
363         TINFL_GET_BYTE(2, r->m_zhdr1);
364         counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
365         if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
366             counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
367         if (counter)
368         {
369             TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
370         }
371     }
372 
373     do
374     {
375         TINFL_GET_BITS(3, r->m_final, 3);
376         r->m_type = r->m_final >> 1;
377         if (r->m_type == 0)
378         {
379             TINFL_SKIP_BITS(5, num_bits & 7);
380             for (counter = 0; counter < 4; ++counter)
381             {
382                 if (num_bits)
383                     TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
384                 else
385                     TINFL_GET_BYTE(7, r->m_raw_header[counter]);
386             }
387             if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^ (r->m_raw_header[2] | (r->m_raw_header[3] << 8))))
388             {
389                 TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
390             }
391             while ((counter) && (num_bits))
392             {
393                 TINFL_GET_BITS(51, dist, 8);
394                 while (pOut_buf_cur >= pOut_buf_end)
395                 {
396                     TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
397                 }
398                 *pOut_buf_cur++ = (mz_uint8)dist;
399                 counter--;
400             }
401             while (counter)
402             {
403                 size_t n;
404                 while (pOut_buf_cur >= pOut_buf_end)
405                 {
406                     TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
407                 }
408                 while (pIn_buf_cur >= pIn_buf_end)
409                 {
410                     TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
411                 }
412                 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
413                 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
414                 pIn_buf_cur += n;
415                 pOut_buf_cur += n;
416                 counter -= (mz_uint)n;
417             }
418         }
419         else if (r->m_type == 3)
420         {
421             TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
422         }
423         else
424         {
425             if (r->m_type == 1)
426             {
427                 mz_uint8 *p = r->m_tables[0].m_code_size;
428                 mz_uint i;
429                 r->m_table_sizes[0] = 288;
430                 r->m_table_sizes[1] = 32;
431                 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
432                 for (i = 0; i <= 143; ++i)
433                     *p++ = 8;
434                 for (; i <= 255; ++i)
435                     *p++ = 9;
436                 for (; i <= 279; ++i)
437                     *p++ = 7;
438                 for (; i <= 287; ++i)
439                     *p++ = 8;
440             }
441             else
442             {
443                 for (counter = 0; counter < 3; counter++)
444                 {
445                     TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
446                     r->m_table_sizes[counter] += s_min_table_sizes[counter];
447                 }
448                 MZ_CLEAR_ARR(r->m_tables[2].m_code_size);
449                 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
450                 {
451                     mz_uint s;
452                     TINFL_GET_BITS(14, s, 3);
453                     r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
454                 }
455                 r->m_table_sizes[2] = 19;
456             }
457             for (; (int)r->m_type >= 0; r->m_type--)
458             {
459                 int tree_next, tree_cur;
460                 tinfl_huff_table *pTable;
461                 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
462                 pTable = &r->m_tables[r->m_type];
463                 MZ_CLEAR_ARR(total_syms);
464                 MZ_CLEAR_ARR(pTable->m_look_up);
465                 MZ_CLEAR_ARR(pTable->m_tree);
466                 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
467                     total_syms[pTable->m_code_size[i]]++;
468                 used_syms = 0, total = 0;
469                 next_code[0] = next_code[1] = 0;
470                 for (i = 1; i <= 15; ++i)
471                 {
472                     used_syms += total_syms[i];
473                     next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
474                 }
475                 if ((65536 != total) && (used_syms > 1))
476                 {
477                     TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
478                 }
479                 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
480                 {
481                     mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
482                     if (!code_size)
483                         continue;
484                     cur_code = next_code[code_size]++;
485                     for (l = code_size; l > 0; l--, cur_code >>= 1)
486                         rev_code = (rev_code << 1) | (cur_code & 1);
487                     if (code_size <= TINFL_FAST_LOOKUP_BITS)
488                     {
489                         mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
490                         while (rev_code < TINFL_FAST_LOOKUP_SIZE)
491                         {
492                             pTable->m_look_up[rev_code] = k;
493                             rev_code += (1 << code_size);
494                         }
495                         continue;
496                     }
497                     if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
498                     {
499                         pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
500                         tree_cur = tree_next;
501                         tree_next -= 2;
502                     }
503                     rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
504                     for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
505                     {
506                         tree_cur -= ((rev_code >>= 1) & 1);
507                         if (!pTable->m_tree[-tree_cur - 1])
508                         {
509                             pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
510                             tree_cur = tree_next;
511                             tree_next -= 2;
512                         }
513                         else
514                             tree_cur = pTable->m_tree[-tree_cur - 1];
515                     }
516                     tree_cur -= ((rev_code >>= 1) & 1);
517                     pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
518                 }
519                 if (r->m_type == 2)
520                 {
521                     for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
522                     {
523                         mz_uint s;
524                         TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
525                         if (dist < 16)
526                         {
527                             r->m_len_codes[counter++] = (mz_uint8)dist;
528                             continue;
529                         }
530                         if ((dist == 16) && (!counter))
531                         {
532                             TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
533                         }
534                         num_extra = "\02\03\07"[dist - 16];
535                         TINFL_GET_BITS(18, s, num_extra);
536                         s += "\03\03\013"[dist - 16];
537                         TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
538                         counter += s;
539                     }
540                     if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
541                     {
542                         TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
543                     }
544                     TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
545                     TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
546                 }
547             }
548             for (;;)
549             {
550                 mz_uint8 *pSrc;
551                 for (;;)
552                 {
553                     if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
554                     {
555                         TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
556                         if (counter >= 256)
557                             break;
558                         while (pOut_buf_cur >= pOut_buf_end)
559                         {
560                             TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
561                         }
562                         *pOut_buf_cur++ = (mz_uint8)counter;
563                     }
564                     else
565                     {
566                         int sym2;
567                         mz_uint code_len;
568 #if TINFL_USE_64BIT_BITBUF
569                         if (num_bits < 30)
570                         {
571                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
572                             pIn_buf_cur += 4;
573                             num_bits += 32;
574                         }
575 #else
576                         if (num_bits < 15)
577                         {
578                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
579                             pIn_buf_cur += 2;
580                             num_bits += 16;
581                         }
582 #endif
583                         if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
584                             code_len = sym2 >> 9;
585                         else
586                         {
587                             code_len = TINFL_FAST_LOOKUP_BITS;
588                             do
589                             {
590                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
591                             } while (sym2 < 0);
592                         }
593                         counter = sym2;
594                         bit_buf >>= code_len;
595                         num_bits -= code_len;
596                         if (counter & 256)
597                             break;
598 
599 #if !TINFL_USE_64BIT_BITBUF
600                         if (num_bits < 15)
601                         {
602                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
603                             pIn_buf_cur += 2;
604                             num_bits += 16;
605                         }
606 #endif
607                         if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
608                             code_len = sym2 >> 9;
609                         else
610                         {
611                             code_len = TINFL_FAST_LOOKUP_BITS;
612                             do
613                             {
614                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
615                             } while (sym2 < 0);
616                         }
617                         bit_buf >>= code_len;
618                         num_bits -= code_len;
619 
620                         pOut_buf_cur[0] = (mz_uint8)counter;
621                         if (sym2 & 256)
622                         {
623                             pOut_buf_cur++;
624                             counter = sym2;
625                             break;
626                         }
627                         pOut_buf_cur[1] = (mz_uint8)sym2;
628                         pOut_buf_cur += 2;
629                     }
630                 }
631                 if ((counter &= 511) == 256)
632                     break;
633 
634                 num_extra = s_length_extra[counter - 257];
635                 counter = s_length_base[counter - 257];
636                 if (num_extra)
637                 {
638                     mz_uint extra_bits;
639                     TINFL_GET_BITS(25, extra_bits, num_extra);
640                     counter += extra_bits;
641                 }
642 
643                 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
644                 num_extra = s_dist_extra[dist];
645                 dist = s_dist_base[dist];
646                 if (num_extra)
647                 {
648                     mz_uint extra_bits;
649                     TINFL_GET_BITS(27, extra_bits, num_extra);
650                     dist += extra_bits;
651                 }
652 
653                 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
654                 if ((dist == 0 || dist > dist_from_out_buf_start || dist_from_out_buf_start == 0) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
655                 {
656                     TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
657                 }
658 
659                 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
660 
661                 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
662                 {
663                     while (counter--)
664                     {
665                         while (pOut_buf_cur >= pOut_buf_end)
666                         {
667                             TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
668                         }
669                         *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
670                     }
671                     continue;
672                 }
673 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
674                 else if ((counter >= 9) && (counter <= dist))
675                 {
676                     const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
677                     do
678                     {
679 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
680 						memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
681 #else
682                         ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
683                         ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
684 #endif
685                         pOut_buf_cur += 8;
686                     } while ((pSrc += 8) < pSrc_end);
687                     if ((counter &= 7) < 3)
688                     {
689                         if (counter)
690                         {
691                             pOut_buf_cur[0] = pSrc[0];
692                             if (counter > 1)
693                                 pOut_buf_cur[1] = pSrc[1];
694                             pOut_buf_cur += counter;
695                         }
696                         continue;
697                     }
698                 }
699 #endif
700                 while(counter>2)
701                 {
702                     pOut_buf_cur[0] = pSrc[0];
703                     pOut_buf_cur[1] = pSrc[1];
704                     pOut_buf_cur[2] = pSrc[2];
705                     pOut_buf_cur += 3;
706                     pSrc += 3;
707 					counter -= 3;
708                 }
709                 if (counter > 0)
710                 {
711                     pOut_buf_cur[0] = pSrc[0];
712                     if (counter > 1)
713                         pOut_buf_cur[1] = pSrc[1];
714                     pOut_buf_cur += counter;
715                 }
716             }
717         }
718     } while (!(r->m_final & 1));
719 
720     /* Ensure byte alignment and put back any bytes from the bitbuf if we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
721     /* I'm being super conservative here. A number of simplifications can be made to the byte alignment part, and the Adler32 check shouldn't ever need to worry about reading from the bitbuf now. */
722     TINFL_SKIP_BITS(32, num_bits & 7);
723     while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
724     {
725         --pIn_buf_cur;
726         num_bits -= 8;
727     }
728     bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
729     MZ_ASSERT(!num_bits); /* if this assert fires then we've read beyond the end of non-deflate/zlib streams with following data (such as gzip streams). */
730 
731     if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
732     {
733         for (counter = 0; counter < 4; ++counter)
734         {
735             mz_uint s;
736             if (num_bits)
737                 TINFL_GET_BITS(41, s, 8);
738             else
739                 TINFL_GET_BYTE(42, s);
740             r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
741         }
742     }
743     TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
744 
745     TINFL_CR_FINISH
746 
747 common_exit:
748     /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
749     /* Put back any bytes from the bitbuf in case we've looked ahead too far on gzip, or other Deflate streams followed by arbitrary data. */
750     /* We need to be very careful here to NOT push back any bytes we definitely know we need to make forward progress, though, or we'll lock the caller up into an inf loop. */
751     if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
752     {
753         while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
754         {
755             --pIn_buf_cur;
756             num_bits -= 8;
757         }
758     }
759     r->m_num_bits = num_bits;
760     r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
761     r->m_dist = dist;
762     r->m_counter = counter;
763     r->m_num_extra = num_extra;
764     r->m_dist_from_out_buf_start = dist_from_out_buf_start;
765     *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
766     *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
767     if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
768     {
769         const mz_uint8 *ptr = pOut_buf_next;
770         size_t buf_len = *pOut_buf_size;
771         mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
772         size_t block_len = buf_len % 5552;
773         while (buf_len)
774         {
775             for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
776             {
777                 s1 += ptr[0], s2 += s1;
778                 s1 += ptr[1], s2 += s1;
779                 s1 += ptr[2], s2 += s1;
780                 s1 += ptr[3], s2 += s1;
781                 s1 += ptr[4], s2 += s1;
782                 s1 += ptr[5], s2 += s1;
783                 s1 += ptr[6], s2 += s1;
784                 s1 += ptr[7], s2 += s1;
785             }
786             for (; i < block_len; ++i)
787                 s1 += *ptr++, s2 += s1;
788             s1 %= 65521U, s2 %= 65521U;
789             buf_len -= block_len;
790             block_len = 5552;
791         }
792         r->m_check_adler32 = (s2 << 16) + s1;
793         if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
794             status = TINFL_STATUS_ADLER32_MISMATCH;
795     }
796     return status;
797 }
798 
799 #ifdef __cplusplus
800 }
801 #endif
802 
803 #endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
804  /**************************************************************************
805  *
806  * Copyright 2013-2014 RAD Game Tools and Valve Software
807  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
808  * Copyright 2016 Martin Raiber
809  * All Rights Reserved.
810  *
811  * Permission is hereby granted, free of charge, to any person obtaining a copy
812  * of this software and associated documentation files (the "Software"), to deal
813  * in the Software without restriction, including without limitation the rights
814  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
815  * copies of the Software, and to permit persons to whom the Software is
816  * furnished to do so, subject to the following conditions:
817  *
818  * The above copyright notice and this permission notice shall be included in
819  * all copies or substantial portions of the Software.
820  *
821  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
822  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
823  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
824  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
825  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
826  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
827  * THE SOFTWARE.
828  *
829  **************************************************************************/
830 
831 
832 #ifndef MINIZ_NO_ARCHIVE_APIS
833 
834 #ifdef __cplusplus
835 extern "C" {
836 #endif
837 
838 /* ------------------- .ZIP archive reading */
839 
840 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
841 
842 /* Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. */
843 enum
844 {
845     /* ZIP archive identifiers and record sizes */
846     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
847     MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
848     MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
849     MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
850     MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
851     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
852 
853     /* ZIP64 archive identifier and record sizes */
854     MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
855     MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
856     MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
857     MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
858     MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
859     MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
860     MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
861     MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
862 
863     /* Central directory header record offsets */
864     MZ_ZIP_CDH_SIG_OFS = 0,
865     MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
866     MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
867     MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
868     MZ_ZIP_CDH_METHOD_OFS = 10,
869     MZ_ZIP_CDH_FILE_TIME_OFS = 12,
870     MZ_ZIP_CDH_FILE_DATE_OFS = 14,
871     MZ_ZIP_CDH_CRC32_OFS = 16,
872     MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
873     MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
874     MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
875     MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
876     MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
877     MZ_ZIP_CDH_DISK_START_OFS = 34,
878     MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
879     MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
880     MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
881 
882     /* Local directory header offsets */
883     MZ_ZIP_LDH_SIG_OFS = 0,
884     MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
885     MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
886     MZ_ZIP_LDH_METHOD_OFS = 8,
887     MZ_ZIP_LDH_FILE_TIME_OFS = 10,
888     MZ_ZIP_LDH_FILE_DATE_OFS = 12,
889     MZ_ZIP_LDH_CRC32_OFS = 14,
890     MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
891     MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
892     MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
893     MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
894     MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
895 
896     /* End of central directory offsets */
897     MZ_ZIP_ECDH_SIG_OFS = 0,
898     MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
899     MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
900     MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
901     MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
902     MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
903     MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
904     MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
905 
906     /* ZIP64 End of central directory locator offsets */
907     MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */
908     MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */
909     MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */
910     MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
911 
912     /* ZIP64 End of central directory header offsets */
913     MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */
914     MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */
915     MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */
916     MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */
917     MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */
918     MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */
919     MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
920     MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */
921     MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */
922     MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */
923     MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
924     MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
925     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
926     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
927     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
928     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
929     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
930 };
931 
932 typedef struct
933 {
934     void *m_p;
935     size_t m_size, m_capacity;
936     mz_uint m_element_size;
937 } mz_zip_array;
938 
939 struct mz_zip_internal_state_tag
940 {
941     mz_zip_array m_central_dir;
942     mz_zip_array m_central_dir_offsets;
943     mz_zip_array m_sorted_central_dir_offsets;
944 
945     /* The flags passed in when the archive is initially opened. */
946     uint32_t m_init_flags;
947 
948     /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
949     mz_bool m_zip64;
950 
951     /* MZ_TRUE if we found zip64 extended info in the central directory (m_zip64 will also be slammed to true too, even if we didn't find a zip64 end of central dir header, etc.) */
952     mz_bool m_zip64_has_extended_info_fields;
953 
954     void *m_pMem;
955 };
956 
957 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
958 
959 #if defined(DEBUG) || defined(_DEBUG)
mz_zip_array_range_check(const mz_zip_array * pArray,mz_uint index)960 static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
961 {
962     MZ_ASSERT(index < pArray->m_size);
963     return index;
964 }
965 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
966 #else
967 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
968 #endif
969 
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)970 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
971 {
972     pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
973     memset(pArray, 0, sizeof(mz_zip_array));
974 }
975 
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)976 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
977 {
978     void *pNew_p;
979     size_t new_capacity = min_new_capacity;
980     MZ_ASSERT(pArray->m_element_size);
981     if (pArray->m_capacity >= min_new_capacity)
982         return MZ_TRUE;
983     if (growing)
984     {
985         new_capacity = MZ_MAX(1, pArray->m_capacity);
986         while (new_capacity < min_new_capacity)
987             new_capacity *= 2;
988     }
989     if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
990         return MZ_FALSE;
991     pArray->m_p = pNew_p;
992     pArray->m_capacity = new_capacity;
993     return MZ_TRUE;
994 }
995 
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)996 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
997 {
998     if (new_size > pArray->m_capacity)
999     {
1000         if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
1001             return MZ_FALSE;
1002     }
1003     pArray->m_size = new_size;
1004     return MZ_TRUE;
1005 }
1006 
mz_zip_set_error(mz_zip_archive * pZip,mz_zip_error err_num)1007 static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
1008 {
1009     if (pZip)
1010         pZip->m_last_error = err_num;
1011     return MZ_FALSE;
1012 }
1013 
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint flags)1014 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
1015 {
1016     (void)flags;
1017     if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
1018         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1019 
1020     if (!pZip->m_pAlloc)
1021         pZip->m_pAlloc = miniz_def_alloc_func;
1022     if (!pZip->m_pFree)
1023         pZip->m_pFree = miniz_def_free_func;
1024     if (!pZip->m_pRealloc)
1025         pZip->m_pRealloc = miniz_def_realloc_func;
1026 
1027     pZip->m_archive_size = 0;
1028     pZip->m_central_directory_file_ofs = 0;
1029     pZip->m_total_files = 0;
1030     pZip->m_last_error = MZ_ZIP_NO_ERROR;
1031 
1032     if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
1033         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1034 
1035     memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
1036     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
1037     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
1038     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
1039     pZip->m_pState->m_init_flags = flags;
1040     pZip->m_pState->m_zip64 = MZ_FALSE;
1041     pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
1042 
1043     pZip->m_zip_mode = MZ_ZIP_MODE_READING;
1044 
1045     return MZ_TRUE;
1046 }
1047 
mz_zip_reader_filename_less(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,mz_uint r_index)1048 static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index)
1049 {
1050     const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
1051     const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
1052     mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1053     mz_uint8 l = 0, r = 0;
1054     pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1055     pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1056     pE = pL + MZ_MIN(l_len, r_len);
1057     while (pL < pE)
1058     {
1059         if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
1060             break;
1061         pL++;
1062         pR++;
1063     }
1064     return (pL == pE) ? (l_len < r_len) : (l < r);
1065 }
1066 
1067 #define MZ_SWAP_UINT32(a, b) \
1068     do                       \
1069     {                        \
1070         mz_uint32 t = a;     \
1071         a = b;               \
1072         b = t;               \
1073     }                        \
1074     MZ_MACRO_END
1075 
1076 /* Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) */
mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive * pZip)1077 static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
1078 {
1079     mz_zip_internal_state *pState = pZip->m_pState;
1080     const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
1081     const mz_zip_array *pCentral_dir = &pState->m_central_dir;
1082     mz_uint32 *pIndices;
1083     mz_uint32 start, end;
1084     const mz_uint32 size = pZip->m_total_files;
1085 
1086     if (size <= 1U)
1087         return;
1088 
1089     pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
1090 
1091     start = (size - 2U) >> 1U;
1092     for (;;)
1093     {
1094         mz_uint64 child, root = start;
1095         for (;;)
1096         {
1097             if ((child = (root << 1U) + 1U) >= size)
1098                 break;
1099             child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
1100             if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
1101                 break;
1102             MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
1103             root = child;
1104         }
1105         if (!start)
1106             break;
1107         start--;
1108     }
1109 
1110     end = size - 1;
1111     while (end > 0)
1112     {
1113         mz_uint64 child, root = 0;
1114         MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
1115         for (;;)
1116         {
1117             if ((child = (root << 1U) + 1U) >= end)
1118                 break;
1119             child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
1120             if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
1121                 break;
1122             MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
1123             root = child;
1124         }
1125         end--;
1126     }
1127 }
1128 
mz_zip_reader_locate_header_sig(mz_zip_archive * pZip,mz_uint32 record_sig,mz_uint32 record_size,mz_int64 * pOfs)1129 static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
1130 {
1131     mz_int64 cur_file_ofs;
1132     mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
1133     mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
1134 
1135     /* Basic sanity checks - reject files which are too small */
1136     if (pZip->m_archive_size < record_size)
1137         return MZ_FALSE;
1138 
1139     /* Find the record by scanning the file from the end towards the beginning. */
1140     cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
1141     for (;;)
1142     {
1143         int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
1144 
1145         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
1146             return MZ_FALSE;
1147 
1148         for (i = n - 4; i >= 0; --i)
1149         {
1150             mz_uint s = MZ_READ_LE32(pBuf + i);
1151             if (s == record_sig)
1152             {
1153                 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
1154                     break;
1155             }
1156         }
1157 
1158         if (i >= 0)
1159         {
1160             cur_file_ofs += i;
1161             break;
1162         }
1163 
1164         /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
1165         if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
1166             return MZ_FALSE;
1167 
1168         cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
1169     }
1170 
1171     *pOfs = cur_file_ofs;
1172     return MZ_TRUE;
1173 }
1174 
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint flags)1175 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
1176 {
1177     mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
1178     mz_uint64 cdir_ofs = 0;
1179     mz_int64 cur_file_ofs = 0;
1180     const mz_uint8 *p;
1181 
1182     mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
1183     mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
1184     mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
1185     mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
1186     mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
1187 
1188     mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
1189     mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
1190 
1191     mz_uint64 zip64_end_of_central_dir_ofs = 0;
1192 
1193     /* Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. */
1194     if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
1195         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
1196 
1197     if (!mz_zip_reader_locate_header_sig(pZip, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE, &cur_file_ofs))
1198         return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
1199 
1200     /* Read and verify the end of central directory record. */
1201     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
1202         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1203 
1204     if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
1205         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
1206 
1207     if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
1208     {
1209         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs - MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE, pZip64_locator, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
1210         {
1211             if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
1212             {
1213                 zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
1214                 if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
1215                     return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
1216 
1217                 if (pZip->m_pRead(pZip->m_pIO_opaque, zip64_end_of_central_dir_ofs, pZip64_end_of_central_dir, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
1218                 {
1219                     if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
1220                     {
1221                         pZip->m_pState->m_zip64 = MZ_TRUE;
1222                     }
1223                 }
1224             }
1225         }
1226     }
1227 
1228     pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
1229     cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
1230     num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
1231     cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
1232     cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
1233     cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
1234 
1235     if (pZip->m_pState->m_zip64)
1236     {
1237         mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
1238         mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
1239         mz_uint64 zip64_cdir_total_entries_on_this_disk = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
1240         mz_uint64 zip64_size_of_end_of_central_dir_record = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS);
1241         mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
1242 
1243         if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
1244             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1245 
1246         if (zip64_total_num_of_disks != 1U)
1247             return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1248 
1249         /* Check for miniz's practical limits */
1250         if (zip64_cdir_total_entries > (mz_uint64)MZ_UINT32_MAX)
1251             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
1252 
1253         pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
1254 
1255         if (zip64_cdir_total_entries_on_this_disk > (mz_uint64)MZ_UINT32_MAX)
1256             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
1257 
1258         cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
1259 
1260         /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
1261         if (zip64_size_of_central_directory > (mz_uint64)MZ_UINT32_MAX)
1262             return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
1263 
1264         cdir_size = (mz_uint32)zip64_size_of_central_directory;
1265 
1266         num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
1267 
1268         cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
1269 
1270         cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
1271     }
1272 
1273     if (pZip->m_total_files != cdir_entries_on_this_disk)
1274         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1275 
1276     if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
1277         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1278 
1279     if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
1280         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1281 
1282     if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
1283         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1284 
1285     pZip->m_central_directory_file_ofs = cdir_ofs;
1286 
1287     if (pZip->m_total_files)
1288     {
1289         mz_uint i, n;
1290         /* Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and possibly another to hold the sorted indices. */
1291         if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
1292             (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
1293             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1294 
1295         if (sort_central_dir)
1296         {
1297             if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
1298                 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1299         }
1300 
1301         if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
1302             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1303 
1304         /* Now create an index into the central directory file records, do some basic sanity checking on each record */
1305         p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
1306         for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
1307         {
1308             mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
1309             mz_uint64 comp_size, decomp_size, local_header_ofs;
1310 
1311             if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
1312                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1313 
1314             MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p);
1315 
1316             if (sort_central_dir)
1317                 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
1318 
1319             comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
1320             decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
1321             local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
1322             filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1323             ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
1324 
1325             if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
1326                 (ext_data_size) &&
1327                 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
1328             {
1329                 /* Attempt to find zip64 extended information field in the entry's extra data */
1330                 mz_uint32 extra_size_remaining = ext_data_size;
1331 
1332                 if (extra_size_remaining)
1333                 {
1334 					const mz_uint8 *pExtra_data;
1335 					void* buf = NULL;
1336 
1337 					if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
1338 					{
1339 						buf = MZ_MALLOC(ext_data_size);
1340 						if(buf==NULL)
1341 							return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1342 
1343 						if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size, buf, ext_data_size) != ext_data_size)
1344 						{
1345 							MZ_FREE(buf);
1346 							return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1347 						}
1348 
1349 						pExtra_data = (mz_uint8*)buf;
1350 					}
1351 					else
1352 					{
1353 						pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
1354 					}
1355 
1356                     do
1357                     {
1358                         mz_uint32 field_id;
1359                         mz_uint32 field_data_size;
1360 
1361 						if (extra_size_remaining < (sizeof(mz_uint16) * 2))
1362 						{
1363 							MZ_FREE(buf);
1364 							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1365 						}
1366 
1367                         field_id = MZ_READ_LE16(pExtra_data);
1368                         field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
1369 
1370 						if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
1371 						{
1372 							MZ_FREE(buf);
1373 							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1374 						}
1375 
1376                         if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
1377                         {
1378                             /* Ok, the archive didn't have any zip64 headers but it uses a zip64 extended information field so mark it as zip64 anyway (this can occur with infozip's zip util when it reads compresses files from stdin). */
1379                             pZip->m_pState->m_zip64 = MZ_TRUE;
1380                             pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
1381                             break;
1382                         }
1383 
1384                         pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
1385                         extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
1386                     } while (extra_size_remaining);
1387 
1388 					MZ_FREE(buf);
1389                 }
1390             }
1391 
1392             /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
1393             if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
1394             {
1395                 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
1396                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1397             }
1398 
1399             disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
1400             if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
1401                 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
1402 
1403             if (comp_size != MZ_UINT32_MAX)
1404             {
1405                 if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size)
1406                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1407             }
1408 
1409             bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1410             if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
1411                 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
1412 
1413             if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n)
1414                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1415 
1416             n -= total_header_size;
1417             p += total_header_size;
1418         }
1419     }
1420 
1421     if (sort_central_dir)
1422         mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
1423 
1424     return MZ_TRUE;
1425 }
1426 
mz_zip_reader_end_internal(mz_zip_archive * pZip,mz_bool set_last_error)1427 static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
1428 {
1429     mz_bool status = MZ_TRUE;
1430 
1431     if (!pZip)
1432         return MZ_FALSE;
1433 
1434     if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
1435     {
1436         if (set_last_error)
1437             pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
1438 
1439         return MZ_FALSE;
1440     }
1441 
1442     if (pZip->m_pState)
1443     {
1444         mz_zip_internal_state *pState = pZip->m_pState;
1445         pZip->m_pState = NULL;
1446 
1447         mz_zip_array_clear(pZip, &pState->m_central_dir);
1448         mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
1449         mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
1450 
1451         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
1452     }
1453     pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
1454 
1455     return status;
1456 }
1457 
mz_zip_reader_end(mz_zip_archive * pZip)1458 mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
1459 {
1460     return mz_zip_reader_end_internal(pZip, MZ_TRUE);
1461 }
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint flags)1462 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
1463 {
1464     if ((!pZip) || (!pZip->m_pRead))
1465         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1466 
1467     if (!mz_zip_reader_init_internal(pZip, flags))
1468         return MZ_FALSE;
1469 
1470     pZip->m_zip_type = MZ_ZIP_TYPE_USER;
1471     pZip->m_archive_size = size;
1472 
1473     if (!mz_zip_reader_read_central_dir(pZip, flags))
1474     {
1475         mz_zip_reader_end_internal(pZip, MZ_FALSE);
1476         return MZ_FALSE;
1477     }
1478 
1479     return MZ_TRUE;
1480 }
1481 
mz_zip_get_cdh(mz_zip_archive * pZip,mz_uint file_index)1482 static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
1483 {
1484     if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
1485         return NULL;
1486     return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
1487 }
1488 
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)1489 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
1490 {
1491     mz_uint m_bit_flag;
1492     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1493     if (!p)
1494     {
1495         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1496         return MZ_FALSE;
1497     }
1498 
1499     m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1500     return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
1501 }
1502 
mz_zip_reader_is_file_supported(mz_zip_archive * pZip,mz_uint file_index)1503 mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
1504 {
1505     mz_uint bit_flag;
1506     mz_uint method;
1507 
1508     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1509     if (!p)
1510     {
1511         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1512         return MZ_FALSE;
1513     }
1514 
1515     method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
1516     bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1517 
1518     if ((method != 0) && (method != MZ_DEFLATED))
1519     {
1520         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
1521         return MZ_FALSE;
1522     }
1523 
1524     if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
1525     {
1526         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
1527         return MZ_FALSE;
1528     }
1529 
1530     if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
1531     {
1532         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
1533         return MZ_FALSE;
1534     }
1535 
1536     return MZ_TRUE;
1537 }
1538 
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)1539 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
1540 {
1541     mz_uint filename_len, attribute_mapping_id, external_attr;
1542     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1543     if (!p)
1544     {
1545         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1546         return MZ_FALSE;
1547     }
1548 
1549     filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1550     if (filename_len)
1551     {
1552         if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
1553             return MZ_TRUE;
1554     }
1555 
1556     /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
1557     /* Most/all zip writers (hopefully) set DOS file/directory attributes in the low 16-bits, so check for the DOS directory flag and ignore the source OS ID in the created by field. */
1558     /* FIXME: Remove this check? Is it necessary - we already check the filename. */
1559     attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
1560     (void)attribute_mapping_id;
1561 
1562     external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
1563     if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
1564     {
1565         return MZ_TRUE;
1566     }
1567 
1568     return MZ_FALSE;
1569 }
1570 
mz_zip_file_stat_internal(mz_zip_archive * pZip,mz_uint file_index,const mz_uint8 * pCentral_dir_header,mz_zip_archive_file_stat * pStat,mz_bool * pFound_zip64_extra_data)1571 static mz_bool mz_zip_file_stat_internal(mz_zip_archive *pZip, mz_uint file_index, const mz_uint8 *pCentral_dir_header, mz_zip_archive_file_stat *pStat, mz_bool *pFound_zip64_extra_data)
1572 {
1573     mz_uint n;
1574     const mz_uint8 *p = pCentral_dir_header;
1575 
1576     if (pFound_zip64_extra_data)
1577         *pFound_zip64_extra_data = MZ_FALSE;
1578 
1579     if ((!p) || (!pStat))
1580         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1581 
1582     /* Extract fields from the central directory record. */
1583     pStat->m_file_index = file_index;
1584     pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
1585     pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
1586     pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
1587     pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
1588     pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
1589     pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
1590     pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
1591     pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
1592     pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
1593     pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
1594     pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
1595 
1596     /* Copy as much of the filename and comment as possible. */
1597     n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1598     n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
1599     memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
1600     pStat->m_filename[n] = '\0';
1601 
1602     n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
1603     n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
1604     pStat->m_comment_size = n;
1605     memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n);
1606     pStat->m_comment[n] = '\0';
1607 
1608     /* Set some flags for convienance */
1609     pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
1610     pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
1611     pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
1612 
1613     /* See if we need to read any zip64 extended information fields. */
1614     /* Confusingly, these zip64 fields can be present even on non-zip64 archives (Debian zip on a huge files from stdin piped to stdout creates them). */
1615     if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
1616     {
1617         /* Attempt to find zip64 extended information field in the entry's extra data */
1618         mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
1619 
1620         if (extra_size_remaining)
1621         {
1622             const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1623 
1624             do
1625             {
1626                 mz_uint32 field_id;
1627                 mz_uint32 field_data_size;
1628 
1629                 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
1630                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1631 
1632                 field_id = MZ_READ_LE16(pExtra_data);
1633                 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
1634 
1635                 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
1636                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1637 
1638                 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
1639                 {
1640                     const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
1641                     mz_uint32 field_data_remaining = field_data_size;
1642 
1643                     if (pFound_zip64_extra_data)
1644                         *pFound_zip64_extra_data = MZ_TRUE;
1645 
1646                     if (pStat->m_uncomp_size == MZ_UINT32_MAX)
1647                     {
1648                         if (field_data_remaining < sizeof(mz_uint64))
1649                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1650 
1651                         pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
1652                         pField_data += sizeof(mz_uint64);
1653                         field_data_remaining -= sizeof(mz_uint64);
1654                     }
1655 
1656                     if (pStat->m_comp_size == MZ_UINT32_MAX)
1657                     {
1658                         if (field_data_remaining < sizeof(mz_uint64))
1659                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1660 
1661                         pStat->m_comp_size = MZ_READ_LE64(pField_data);
1662                         pField_data += sizeof(mz_uint64);
1663                         field_data_remaining -= sizeof(mz_uint64);
1664                     }
1665 
1666                     if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
1667                     {
1668                         if (field_data_remaining < sizeof(mz_uint64))
1669                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1670 
1671                         pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
1672                         pField_data += sizeof(mz_uint64);
1673                         field_data_remaining -= sizeof(mz_uint64);
1674                     }
1675 
1676                     break;
1677                 }
1678 
1679                 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
1680                 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
1681             } while (extra_size_remaining);
1682         }
1683     }
1684 
1685     return MZ_TRUE;
1686 }
1687 
mz_zip_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)1688 static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
1689 {
1690     mz_uint i;
1691     if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
1692         return 0 == memcmp(pA, pB, len);
1693     for (i = 0; i < len; ++i)
1694         if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
1695             return MZ_FALSE;
1696     return MZ_TRUE;
1697 }
1698 
mz_zip_filename_compare(const mz_zip_array * pCentral_dir_array,const mz_zip_array * pCentral_dir_offsets,mz_uint l_index,const char * pR,mz_uint r_len)1699 static MZ_FORCEINLINE int mz_zip_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len)
1700 {
1701     const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE;
1702     mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1703     mz_uint8 l = 0, r = 0;
1704     pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1705     pE = pL + MZ_MIN(l_len, r_len);
1706     while (pL < pE)
1707     {
1708         if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
1709             break;
1710         pL++;
1711         pR++;
1712     }
1713     return (pL == pE) ? (int)(l_len - r_len) : (l - r);
1714 }
1715 
mz_zip_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename,mz_uint32 * pIndex)1716 static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
1717 {
1718     mz_zip_internal_state *pState = pZip->m_pState;
1719     const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
1720     const mz_zip_array *pCentral_dir = &pState->m_central_dir;
1721     mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
1722     const uint32_t size = pZip->m_total_files;
1723     const mz_uint filename_len = (mz_uint)strlen(pFilename);
1724 
1725     if (pIndex)
1726         *pIndex = 0;
1727 
1728     if (size)
1729     {
1730         /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
1731         /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
1732         mz_int64 l = 0, h = (mz_int64)size - 1;
1733 
1734         while (l <= h)
1735         {
1736             mz_int64 m = l + ((h - l) >> 1);
1737             uint32_t file_index = pIndices[(uint32_t)m];
1738 
1739             int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
1740             if (!comp)
1741             {
1742                 if (pIndex)
1743                     *pIndex = file_index;
1744                 return MZ_TRUE;
1745             }
1746             else if (comp < 0)
1747                 l = m + 1;
1748             else
1749                 h = m - 1;
1750         }
1751     }
1752 
1753     return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
1754 }
1755 
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)1756 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
1757 {
1758     mz_uint32 index;
1759     if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
1760         return -1;
1761     else
1762         return (int)index;
1763 }
1764 
mz_zip_reader_locate_file_v2(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags,mz_uint32 * pIndex)1765 mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
1766 {
1767     mz_uint file_index;
1768     size_t name_len, comment_len;
1769 
1770     if (pIndex)
1771         *pIndex = 0;
1772 
1773     if ((!pZip) || (!pZip->m_pState) || (!pName))
1774         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1775 
1776     /* See if we can use a binary search */
1777     if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
1778         (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
1779         ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
1780     {
1781         return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
1782     }
1783 
1784     /* Locate the entry by scanning the entire central directory */
1785     name_len = strlen(pName);
1786     if (name_len > MZ_UINT16_MAX)
1787         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1788 
1789     comment_len = pComment ? strlen(pComment) : 0;
1790     if (comment_len > MZ_UINT16_MAX)
1791         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1792 
1793     for (file_index = 0; file_index < pZip->m_total_files; file_index++)
1794     {
1795         const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index));
1796         mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
1797         const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
1798         if (filename_len < name_len)
1799             continue;
1800         if (comment_len)
1801         {
1802             mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS);
1803             const char *pFile_comment = pFilename + filename_len + file_extra_len;
1804             if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
1805                 continue;
1806         }
1807         if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
1808         {
1809             int ofs = filename_len - 1;
1810             do
1811             {
1812                 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
1813                     break;
1814             } while (--ofs >= 0);
1815             ofs++;
1816             pFilename += ofs;
1817             filename_len -= ofs;
1818         }
1819         if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
1820         {
1821             if (pIndex)
1822                 *pIndex = file_index;
1823             return MZ_TRUE;
1824         }
1825     }
1826 
1827     return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
1828 }
1829 
mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)1830 mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
1831 {
1832     int status = TINFL_STATUS_DONE;
1833     mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
1834     mz_zip_archive_file_stat file_stat;
1835     void *pRead_buf;
1836     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
1837     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
1838     tinfl_decompressor inflator;
1839 
1840     if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
1841         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1842 
1843     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
1844         return MZ_FALSE;
1845 
1846     /* A directory or zero length file */
1847     if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
1848         return MZ_TRUE;
1849 
1850     /* Encryption and patch files are not supported. */
1851     if (file_stat.m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG))
1852         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
1853 
1854     /* This function only supports decompressing stored and deflate. */
1855     if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
1856         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
1857 
1858     /* Ensure supplied output buffer is large enough. */
1859     needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
1860     if (buf_size < needed_size)
1861         return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
1862 
1863     /* Read and parse the local directory entry. */
1864     cur_file_ofs = file_stat.m_local_header_ofs;
1865     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
1866         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1867 
1868     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
1869         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1870 
1871     cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
1872     if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
1873         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
1874 
1875     if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
1876     {
1877         /* The file is stored or the caller has requested the compressed data. */
1878         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
1879             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
1880 
1881 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
1882         if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
1883         {
1884             if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
1885                 return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
1886         }
1887 #endif
1888 
1889         return MZ_TRUE;
1890     }
1891 
1892     /* Decompress the file either directly from memory or from a file input buffer. */
1893     tinfl_init(&inflator);
1894 
1895     if (pZip->m_pState->m_pMem)
1896     {
1897         /* Read directly from the archive in memory. */
1898         pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
1899         read_buf_size = read_buf_avail = file_stat.m_comp_size;
1900         comp_remaining = 0;
1901     }
1902     else if (pUser_read_buf)
1903     {
1904         /* Use a user provided read buffer. */
1905         if (!user_read_buf_size)
1906             return MZ_FALSE;
1907         pRead_buf = (mz_uint8 *)pUser_read_buf;
1908         read_buf_size = user_read_buf_size;
1909         read_buf_avail = 0;
1910         comp_remaining = file_stat.m_comp_size;
1911     }
1912     else
1913     {
1914         /* Temporarily allocate a read buffer. */
1915         read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
1916         if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
1917             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
1918 
1919         if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
1920             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
1921 
1922         read_buf_avail = 0;
1923         comp_remaining = file_stat.m_comp_size;
1924     }
1925 
1926     do
1927     {
1928         /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
1929         size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
1930         if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
1931         {
1932             read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
1933             if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
1934             {
1935                 status = TINFL_STATUS_FAILED;
1936                 mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
1937                 break;
1938             }
1939             cur_file_ofs += read_buf_avail;
1940             comp_remaining -= read_buf_avail;
1941             read_buf_ofs = 0;
1942         }
1943         in_buf_size = (size_t)read_buf_avail;
1944         status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0));
1945         read_buf_avail -= in_buf_size;
1946         read_buf_ofs += in_buf_size;
1947         out_buf_ofs += out_buf_size;
1948     } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
1949 
1950     if (status == TINFL_STATUS_DONE)
1951     {
1952         /* Make sure the entire file was decompressed, and check its CRC. */
1953         if (out_buf_ofs != file_stat.m_uncomp_size)
1954         {
1955             mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
1956             status = TINFL_STATUS_FAILED;
1957         }
1958 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
1959         else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
1960         {
1961             mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
1962             status = TINFL_STATUS_FAILED;
1963         }
1964 #endif
1965     }
1966 
1967     if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
1968         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
1969 
1970     return status == TINFL_STATUS_DONE;
1971 }
1972 
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)1973 mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags)
1974 {
1975     return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
1976 }
1977 
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)1978 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
1979 {
1980     mz_uint64 comp_size, uncomp_size, alloc_size;
1981     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
1982     void *pBuf;
1983 
1984     if (pSize)
1985         *pSize = 0;
1986 
1987     if (!p)
1988     {
1989         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
1990         return NULL;
1991     }
1992 
1993     comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
1994     uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
1995 
1996     alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
1997     if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
1998     {
1999         mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
2000         return NULL;
2001     }
2002 
2003     if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
2004     {
2005         mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
2006         return NULL;
2007     }
2008 
2009     if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
2010     {
2011         pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
2012         return NULL;
2013     }
2014 
2015     if (pSize)
2016         *pSize = (size_t)alloc_size;
2017     return pBuf;
2018 }
2019 
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)2020 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
2021 {
2022     mz_uint32 file_index;
2023     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
2024     {
2025         if (pSize)
2026             *pSize = 0;
2027         return MZ_FALSE;
2028     }
2029     return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
2030 }
2031 
2032 /* ------------------- Misc utils */
2033 
2034 #if 0 /* unused for now */
2035 mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
2036 {
2037     return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
2038 }
2039 
2040 mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
2041 {
2042     return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
2043 }
2044 
2045 mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
2046 {
2047     mz_zip_error prev_err;
2048 
2049     if (!pZip)
2050         return MZ_ZIP_INVALID_PARAMETER;
2051 
2052     prev_err = pZip->m_last_error;
2053 
2054     pZip->m_last_error = err_num;
2055     return prev_err;
2056 }
2057 
2058 mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
2059 {
2060     if (!pZip)
2061         return MZ_ZIP_INVALID_PARAMETER;
2062 
2063     return pZip->m_last_error;
2064 }
2065 
2066 mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
2067 {
2068     return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
2069 }
2070 
2071 mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
2072 {
2073     mz_zip_error prev_err;
2074 
2075     if (!pZip)
2076         return MZ_ZIP_INVALID_PARAMETER;
2077 
2078     prev_err = pZip->m_last_error;
2079 
2080     pZip->m_last_error = MZ_ZIP_NO_ERROR;
2081     return prev_err;
2082 }
2083 
2084 const char *mz_zip_get_error_string(mz_zip_error mz_err)
2085 {
2086     switch (mz_err)
2087     {
2088         case MZ_ZIP_NO_ERROR:
2089             return "no error";
2090         case MZ_ZIP_UNDEFINED_ERROR:
2091             return "undefined error";
2092         case MZ_ZIP_TOO_MANY_FILES:
2093             return "too many files";
2094         case MZ_ZIP_FILE_TOO_LARGE:
2095             return "file too large";
2096         case MZ_ZIP_UNSUPPORTED_METHOD:
2097             return "unsupported method";
2098         case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
2099             return "unsupported encryption";
2100         case MZ_ZIP_UNSUPPORTED_FEATURE:
2101             return "unsupported feature";
2102         case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
2103             return "failed finding central directory";
2104         case MZ_ZIP_NOT_AN_ARCHIVE:
2105             return "not a ZIP archive";
2106         case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
2107             return "invalid header or archive is corrupted";
2108         case MZ_ZIP_UNSUPPORTED_MULTIDISK:
2109             return "unsupported multidisk archive";
2110         case MZ_ZIP_DECOMPRESSION_FAILED:
2111             return "decompression failed or archive is corrupted";
2112         case MZ_ZIP_COMPRESSION_FAILED:
2113             return "compression failed";
2114         case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
2115             return "unexpected decompressed size";
2116         case MZ_ZIP_CRC_CHECK_FAILED:
2117             return "CRC-32 check failed";
2118         case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
2119             return "unsupported central directory size";
2120         case MZ_ZIP_ALLOC_FAILED:
2121             return "allocation failed";
2122         case MZ_ZIP_FILE_OPEN_FAILED:
2123             return "file open failed";
2124         case MZ_ZIP_FILE_CREATE_FAILED:
2125             return "file create failed";
2126         case MZ_ZIP_FILE_WRITE_FAILED:
2127             return "file write failed";
2128         case MZ_ZIP_FILE_READ_FAILED:
2129             return "file read failed";
2130         case MZ_ZIP_FILE_CLOSE_FAILED:
2131             return "file close failed";
2132         case MZ_ZIP_FILE_SEEK_FAILED:
2133             return "file seek failed";
2134         case MZ_ZIP_FILE_STAT_FAILED:
2135             return "file stat failed";
2136         case MZ_ZIP_INVALID_PARAMETER:
2137             return "invalid parameter";
2138         case MZ_ZIP_INVALID_FILENAME:
2139             return "invalid filename";
2140         case MZ_ZIP_BUF_TOO_SMALL:
2141             return "buffer too small";
2142         case MZ_ZIP_INTERNAL_ERROR:
2143             return "internal error";
2144         case MZ_ZIP_FILE_NOT_FOUND:
2145             return "file not found";
2146         case MZ_ZIP_ARCHIVE_TOO_LARGE:
2147             return "archive is too large";
2148         case MZ_ZIP_VALIDATION_FAILED:
2149             return "validation failed";
2150         case MZ_ZIP_WRITE_CALLBACK_FAILED:
2151             return "write calledback failed";
2152         default:
2153             break;
2154     }
2155 
2156     return "unknown error";
2157 }
2158 
2159 /* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
2160 mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
2161 {
2162     if ((!pZip) || (!pZip->m_pState))
2163         return MZ_FALSE;
2164 
2165     return pZip->m_pState->m_zip64;
2166 }
2167 
2168 size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
2169 {
2170     if ((!pZip) || (!pZip->m_pState))
2171         return 0;
2172 
2173     return pZip->m_pState->m_central_dir.m_size;
2174 }
2175 
2176 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
2177 {
2178     return pZip ? pZip->m_total_files : 0;
2179 }
2180 
2181 mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
2182 {
2183     if (!pZip)
2184         return 0;
2185     return pZip->m_archive_size;
2186 }
2187 
2188 MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
2189 {
2190     if ((!pZip) || (!pZip->m_pState))
2191         return 0;
2192     return pZip->m_pState->m_pFile;
2193 }
2194 
2195 size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
2196 {
2197     if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
2198         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
2199 
2200     return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
2201 }
2202 
2203 mz_bool mz_zip_end(mz_zip_archive *pZip)
2204 {
2205     if (!pZip)
2206         return MZ_FALSE;
2207 
2208     if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
2209         return mz_zip_reader_end(pZip);
2210 
2211     return MZ_FALSE;
2212 }
2213 
2214 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
2215 {
2216     mz_uint n;
2217     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
2218     if (!p)
2219     {
2220         if (filename_buf_size)
2221             pFilename[0] = '\0';
2222         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
2223         return 0;
2224     }
2225     n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
2226     if (filename_buf_size)
2227     {
2228         n = MZ_MIN(n, filename_buf_size - 1);
2229         memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
2230         pFilename[n] = '\0';
2231     }
2232     return n + 1;
2233 }
2234 #endif
2235 
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)2236 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
2237 {
2238     return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
2239 }
2240 
2241 #ifdef __cplusplus
2242 }
2243 #endif
2244 
2245 #endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
2246