1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5  * All Rights Reserved.
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  *
25  **************************************************************************/
26 
27 #include  "miniz.h"
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 /* ------------------- zlib-style API's */
38 
mz_adler32(mz_ulong adler,const unsigned char * ptr,size_t buf_len)39 mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
40 {
41     mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16);
42     size_t block_len = buf_len % 5552;
43     if (!ptr)
44         return MZ_ADLER32_INIT;
45     while (buf_len)
46     {
47         for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
48         {
49             s1 += ptr[0], s2 += s1;
50             s1 += ptr[1], s2 += s1;
51             s1 += ptr[2], s2 += s1;
52             s1 += ptr[3], s2 += s1;
53             s1 += ptr[4], s2 += s1;
54             s1 += ptr[5], s2 += s1;
55             s1 += ptr[6], s2 += s1;
56             s1 += ptr[7], s2 += s1;
57         }
58         for (; i < block_len; ++i)
59             s1 += *ptr++, s2 += s1;
60         s1 %= 65521U, s2 %= 65521U;
61         buf_len -= block_len;
62         block_len = 5552;
63     }
64     return (s2 << 16) + s1;
65 }
66 
67 /* 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/ */
68 #if 0
69     mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
70     {
71         static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
72                                                0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
73         mz_uint32 crcu32 = (mz_uint32)crc;
74         if (!ptr)
75             return MZ_CRC32_INIT;
76         crcu32 = ~crcu32;
77         while (buf_len--)
78         {
79             mz_uint8 b = *ptr++;
80             crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b & 0xF)];
81             crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^ (b >> 4)];
82         }
83         return ~crcu32;
84     }
85 #else
86 /* Faster, but larger CPU cache footprint.
87  */
mz_crc32(mz_ulong crc,const mz_uint8 * ptr,size_t buf_len)88 mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len)
89 {
90     static const mz_uint32 s_crc_table[256] =
91         {
92           0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535,
93           0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD,
94           0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D,
95           0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
96           0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4,
97           0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
98           0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC,
99           0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
100           0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB,
101           0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F,
102           0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB,
103           0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
104           0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA,
105           0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE,
106           0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A,
107           0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
108           0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409,
109           0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
110           0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739,
111           0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
112           0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268,
113           0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0,
114           0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8,
115           0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
116           0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF,
117           0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703,
118           0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7,
119           0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
120           0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE,
121           0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
122           0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6,
123           0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
124           0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D,
125           0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5,
126           0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605,
127           0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
128           0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
129         };
130 
131     mz_uint32 crc32 = (mz_uint32)crc ^ 0xFFFFFFFF;
132     const mz_uint8 *pByte_buf = (const mz_uint8 *)ptr;
133 
134     while (buf_len >= 4)
135     {
136         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
137         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[1]) & 0xFF];
138         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[2]) & 0xFF];
139         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[3]) & 0xFF];
140         pByte_buf += 4;
141         buf_len -= 4;
142     }
143 
144     while (buf_len)
145     {
146         crc32 = (crc32 >> 8) ^ s_crc_table[(crc32 ^ pByte_buf[0]) & 0xFF];
147         ++pByte_buf;
148         --buf_len;
149     }
150 
151     return ~crc32;
152 }
153 #endif
154 
mz_free(void * p)155 void mz_free(void *p)
156 {
157     MZ_FREE(p);
158 }
159 
miniz_def_alloc_func(void * opaque,size_t items,size_t size)160 void *miniz_def_alloc_func(void *opaque, size_t items, size_t size)
161 {
162     (void)opaque, (void)items, (void)size;
163     return MZ_MALLOC(items * size);
164 }
miniz_def_free_func(void * opaque,void * address)165 void miniz_def_free_func(void *opaque, void *address)
166 {
167     (void)opaque, (void)address;
168     MZ_FREE(address);
169 }
miniz_def_realloc_func(void * opaque,void * address,size_t items,size_t size)170 void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size)
171 {
172     (void)opaque, (void)address, (void)items, (void)size;
173     return MZ_REALLOC(address, items * size);
174 }
175 
mz_version(void)176 const char *mz_version(void)
177 {
178     return MZ_VERSION;
179 }
180 
181 #ifndef MINIZ_NO_ZLIB_APIS
182 
mz_deflateInit(mz_streamp pStream,int level)183 int mz_deflateInit(mz_streamp pStream, int level)
184 {
185     return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY);
186 }
187 
mz_deflateInit2(mz_streamp pStream,int level,int method,int window_bits,int mem_level,int strategy)188 int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
189 {
190     tdefl_compressor *pComp;
191     mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
192 
193     if (!pStream)
194         return MZ_STREAM_ERROR;
195     if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
196         return MZ_PARAM_ERROR;
197 
198     pStream->data_type = 0;
199     pStream->adler = MZ_ADLER32_INIT;
200     pStream->msg = NULL;
201     pStream->reserved = 0;
202     pStream->total_in = 0;
203     pStream->total_out = 0;
204     if (!pStream->zalloc)
205         pStream->zalloc = miniz_def_alloc_func;
206     if (!pStream->zfree)
207         pStream->zfree = miniz_def_free_func;
208 
209     pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
210     if (!pComp)
211         return MZ_MEM_ERROR;
212 
213     pStream->state = (struct mz_internal_state *)pComp;
214 
215     if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
216     {
217         mz_deflateEnd(pStream);
218         return MZ_PARAM_ERROR;
219     }
220 
221     return MZ_OK;
222 }
223 
mz_deflateReset(mz_streamp pStream)224 int mz_deflateReset(mz_streamp pStream)
225 {
226     if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
227         return MZ_STREAM_ERROR;
228     pStream->total_in = pStream->total_out = 0;
229     tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
230     return MZ_OK;
231 }
232 
mz_deflate(mz_streamp pStream,int flush)233 int mz_deflate(mz_streamp pStream, int flush)
234 {
235     size_t in_bytes, out_bytes;
236     mz_ulong orig_total_in, orig_total_out;
237     int mz_status = MZ_OK;
238 
239     if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
240         return MZ_STREAM_ERROR;
241     if (!pStream->avail_out)
242         return MZ_BUF_ERROR;
243 
244     if (flush == MZ_PARTIAL_FLUSH)
245         flush = MZ_SYNC_FLUSH;
246 
247     if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
248         return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
249 
250     orig_total_in = pStream->total_in;
251     orig_total_out = pStream->total_out;
252     for (;;)
253     {
254         tdefl_status defl_status;
255         in_bytes = pStream->avail_in;
256         out_bytes = pStream->avail_out;
257 
258         defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
259         pStream->next_in += (mz_uint)in_bytes;
260         pStream->avail_in -= (mz_uint)in_bytes;
261         pStream->total_in += (mz_uint)in_bytes;
262         pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
263 
264         pStream->next_out += (mz_uint)out_bytes;
265         pStream->avail_out -= (mz_uint)out_bytes;
266         pStream->total_out += (mz_uint)out_bytes;
267 
268         if (defl_status < 0)
269         {
270             mz_status = MZ_STREAM_ERROR;
271             break;
272         }
273         else if (defl_status == TDEFL_STATUS_DONE)
274         {
275             mz_status = MZ_STREAM_END;
276             break;
277         }
278         else if (!pStream->avail_out)
279             break;
280         else if ((!pStream->avail_in) && (flush != MZ_FINISH))
281         {
282             if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
283                 break;
284             return MZ_BUF_ERROR; /* Can't make forward progress without some input.
285  */
286         }
287     }
288     return mz_status;
289 }
290 
mz_deflateEnd(mz_streamp pStream)291 int mz_deflateEnd(mz_streamp pStream)
292 {
293     if (!pStream)
294         return MZ_STREAM_ERROR;
295     if (pStream->state)
296     {
297         pStream->zfree(pStream->opaque, pStream->state);
298         pStream->state = NULL;
299     }
300     return MZ_OK;
301 }
302 
mz_deflateBound(mz_streamp pStream,mz_ulong source_len)303 mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
304 {
305     (void)pStream;
306     /* This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) */
307     return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
308 }
309 
mz_compress2(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len,int level)310 int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
311 {
312     int status;
313     mz_stream stream;
314     memset(&stream, 0, sizeof(stream));
315 
316     /* In case mz_ulong is 64-bits (argh I hate longs). */
317     if ((source_len | *pDest_len) > 0xFFFFFFFFU)
318         return MZ_PARAM_ERROR;
319 
320     stream.next_in = pSource;
321     stream.avail_in = (mz_uint32)source_len;
322     stream.next_out = pDest;
323     stream.avail_out = (mz_uint32)*pDest_len;
324 
325     status = mz_deflateInit(&stream, level);
326     if (status != MZ_OK)
327         return status;
328 
329     status = mz_deflate(&stream, MZ_FINISH);
330     if (status != MZ_STREAM_END)
331     {
332         mz_deflateEnd(&stream);
333         return (status == MZ_OK) ? MZ_BUF_ERROR : status;
334     }
335 
336     *pDest_len = stream.total_out;
337     return mz_deflateEnd(&stream);
338 }
339 
mz_compress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)340 int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
341 {
342     return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
343 }
344 
mz_compressBound(mz_ulong source_len)345 mz_ulong mz_compressBound(mz_ulong source_len)
346 {
347     return mz_deflateBound(NULL, source_len);
348 }
349 
350 typedef struct
351 {
352     tinfl_decompressor m_decomp;
353     mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
354     int m_window_bits;
355     mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
356     tinfl_status m_last_status;
357 } inflate_state;
358 
mz_inflateInit2(mz_streamp pStream,int window_bits)359 int mz_inflateInit2(mz_streamp pStream, int window_bits)
360 {
361     inflate_state *pDecomp;
362     if (!pStream)
363         return MZ_STREAM_ERROR;
364     if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
365         return MZ_PARAM_ERROR;
366 
367     pStream->data_type = 0;
368     pStream->adler = 0;
369     pStream->msg = NULL;
370     pStream->total_in = 0;
371     pStream->total_out = 0;
372     pStream->reserved = 0;
373     if (!pStream->zalloc)
374         pStream->zalloc = miniz_def_alloc_func;
375     if (!pStream->zfree)
376         pStream->zfree = miniz_def_free_func;
377 
378     pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
379     if (!pDecomp)
380         return MZ_MEM_ERROR;
381 
382     pStream->state = (struct mz_internal_state *)pDecomp;
383 
384     tinfl_init(&pDecomp->m_decomp);
385     pDecomp->m_dict_ofs = 0;
386     pDecomp->m_dict_avail = 0;
387     pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
388     pDecomp->m_first_call = 1;
389     pDecomp->m_has_flushed = 0;
390     pDecomp->m_window_bits = window_bits;
391 
392     return MZ_OK;
393 }
394 
mz_inflateInit(mz_streamp pStream)395 int mz_inflateInit(mz_streamp pStream)
396 {
397     return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
398 }
399 
mz_inflate(mz_streamp pStream,int flush)400 int mz_inflate(mz_streamp pStream, int flush)
401 {
402     inflate_state *pState;
403     mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
404     size_t in_bytes, out_bytes, orig_avail_in;
405     tinfl_status status;
406 
407     if ((!pStream) || (!pStream->state))
408         return MZ_STREAM_ERROR;
409     if (flush == MZ_PARTIAL_FLUSH)
410         flush = MZ_SYNC_FLUSH;
411     if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
412         return MZ_STREAM_ERROR;
413 
414     pState = (inflate_state *)pStream->state;
415     if (pState->m_window_bits > 0)
416         decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
417     orig_avail_in = pStream->avail_in;
418 
419     first_call = pState->m_first_call;
420     pState->m_first_call = 0;
421     if (pState->m_last_status < 0)
422         return MZ_DATA_ERROR;
423 
424     if (pState->m_has_flushed && (flush != MZ_FINISH))
425         return MZ_STREAM_ERROR;
426     pState->m_has_flushed |= (flush == MZ_FINISH);
427 
428     if ((flush == MZ_FINISH) && (first_call))
429     {
430         /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
431         decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
432         in_bytes = pStream->avail_in;
433         out_bytes = pStream->avail_out;
434         status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
435         pState->m_last_status = status;
436         pStream->next_in += (mz_uint)in_bytes;
437         pStream->avail_in -= (mz_uint)in_bytes;
438         pStream->total_in += (mz_uint)in_bytes;
439         pStream->adler = tinfl_get_adler32(&pState->m_decomp);
440         pStream->next_out += (mz_uint)out_bytes;
441         pStream->avail_out -= (mz_uint)out_bytes;
442         pStream->total_out += (mz_uint)out_bytes;
443 
444         if (status < 0)
445             return MZ_DATA_ERROR;
446         else if (status != TINFL_STATUS_DONE)
447         {
448             pState->m_last_status = TINFL_STATUS_FAILED;
449             return MZ_BUF_ERROR;
450         }
451         return MZ_STREAM_END;
452     }
453     /* flush != MZ_FINISH then we must assume there's more input. */
454     if (flush != MZ_FINISH)
455         decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
456 
457     if (pState->m_dict_avail)
458     {
459         n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
460         memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
461         pStream->next_out += n;
462         pStream->avail_out -= n;
463         pStream->total_out += n;
464         pState->m_dict_avail -= n;
465         pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
466         return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
467     }
468 
469     for (;;)
470     {
471         in_bytes = pStream->avail_in;
472         out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
473 
474         status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags);
475         pState->m_last_status = status;
476 
477         pStream->next_in += (mz_uint)in_bytes;
478         pStream->avail_in -= (mz_uint)in_bytes;
479         pStream->total_in += (mz_uint)in_bytes;
480         pStream->adler = tinfl_get_adler32(&pState->m_decomp);
481 
482         pState->m_dict_avail = (mz_uint)out_bytes;
483 
484         n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
485         memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
486         pStream->next_out += n;
487         pStream->avail_out -= n;
488         pStream->total_out += n;
489         pState->m_dict_avail -= n;
490         pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
491 
492         if (status < 0)
493             return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
494         else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
495             return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
496         else if (flush == MZ_FINISH)
497         {
498             /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
499             if (status == TINFL_STATUS_DONE)
500                 return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
501             /* status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. */
502             else if (!pStream->avail_out)
503                 return MZ_BUF_ERROR;
504         }
505         else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
506             break;
507     }
508 
509     return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
510 }
511 
mz_inflateEnd(mz_streamp pStream)512 int mz_inflateEnd(mz_streamp pStream)
513 {
514     if (!pStream)
515         return MZ_STREAM_ERROR;
516     if (pStream->state)
517     {
518         pStream->zfree(pStream->opaque, pStream->state);
519         pStream->state = NULL;
520     }
521     return MZ_OK;
522 }
523 
mz_uncompress(unsigned char * pDest,mz_ulong * pDest_len,const unsigned char * pSource,mz_ulong source_len)524 int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
525 {
526     mz_stream stream;
527     int status;
528     memset(&stream, 0, sizeof(stream));
529 
530     /* In case mz_ulong is 64-bits (argh I hate longs). */
531     if ((source_len | *pDest_len) > 0xFFFFFFFFU)
532         return MZ_PARAM_ERROR;
533 
534     stream.next_in = pSource;
535     stream.avail_in = (mz_uint32)source_len;
536     stream.next_out = pDest;
537     stream.avail_out = (mz_uint32)*pDest_len;
538 
539     status = mz_inflateInit(&stream);
540     if (status != MZ_OK)
541         return status;
542 
543     status = mz_inflate(&stream, MZ_FINISH);
544     if (status != MZ_STREAM_END)
545     {
546         mz_inflateEnd(&stream);
547         return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
548     }
549     *pDest_len = stream.total_out;
550 
551     return mz_inflateEnd(&stream);
552 }
553 
mz_error(int err)554 const char *mz_error(int err)
555 {
556     static struct
557     {
558         int m_err;
559         const char *m_pDesc;
560     } s_error_descs[] =
561         {
562           { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" }
563         };
564     mz_uint i;
565     for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
566         if (s_error_descs[i].m_err == err)
567             return s_error_descs[i].m_pDesc;
568     return NULL;
569 }
570 
571 #endif /*MINIZ_NO_ZLIB_APIS */
572 
573 #ifdef __cplusplus
574 }
575 #endif
576 
577 /*
578   This is free and unencumbered software released into the public domain.
579 
580   Anyone is free to copy, modify, publish, use, compile, sell, or
581   distribute this software, either in source code form or as a compiled
582   binary, for any purpose, commercial or non-commercial, and by any
583   means.
584 
585   In jurisdictions that recognize copyright laws, the author or authors
586   of this software dedicate any and all copyright interest in the
587   software to the public domain. We make this dedication for the benefit
588   of the public at large and to the detriment of our heirs and
589   successors. We intend this dedication to be an overt act of
590   relinquishment in perpetuity of all present and future rights to this
591   software under copyright law.
592 
593   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
594   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
595   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
596   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
597   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
598   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
599   OTHER DEALINGS IN THE SOFTWARE.
600 
601   For more information, please refer to <http://unlicense.org/>
602 */
603 /**************************************************************************
604  *
605  * Copyright 2013-2014 RAD Game Tools and Valve Software
606  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
607  * All Rights Reserved.
608  *
609  * Permission is hereby granted, free of charge, to any person obtaining a copy
610  * of this software and associated documentation files (the "Software"), to deal
611  * in the Software without restriction, including without limitation the rights
612  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
613  * copies of the Software, and to permit persons to whom the Software is
614  * furnished to do so, subject to the following conditions:
615  *
616  * The above copyright notice and this permission notice shall be included in
617  * all copies or substantial portions of the Software.
618  *
619  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
620  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
621  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
622  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
623  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
624  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
625  * THE SOFTWARE.
626  *
627  **************************************************************************/
628 
629 
630 
631 
632 #ifdef __cplusplus
633 extern "C" {
634 #endif
635 
636 /* ------------------- Low-level Compression (independent from all decompression API's) */
637 
638 /* Purposely making these tables static for faster init and thread safety. */
639 static const mz_uint16 s_tdefl_len_sym[256] =
640     {
641       257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272,
642       273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276,
643       277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278,
644       279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280,
645       281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281,
646       282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282,
647       283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283,
648       284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285
649     };
650 
651 static const mz_uint8 s_tdefl_len_extra[256] =
652     {
653       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
654       4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
655       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
656       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0
657     };
658 
659 static const mz_uint8 s_tdefl_small_dist_sym[512] =
660     {
661       0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11,
662       11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13,
663       13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
664       14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,
665       14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
666       15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
667       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
668       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
669       16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
670       17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
671       17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
672       17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17
673     };
674 
675 static const mz_uint8 s_tdefl_small_dist_extra[512] =
676     {
677       0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
678       5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
679       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
680       6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
681       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
682       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
683       7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
684       7, 7, 7, 7, 7, 7, 7, 7
685     };
686 
687 static const mz_uint8 s_tdefl_large_dist_sym[128] =
688     {
689       0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,
690       26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
691       28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
692     };
693 
694 static const mz_uint8 s_tdefl_large_dist_extra[128] =
695     {
696       0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,
697       12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13,
698       13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13
699     };
700 
701 /* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
702 typedef struct
703 {
704     mz_uint16 m_key, m_sym_index;
705 } tdefl_sym_freq;
tdefl_radix_sort_syms(mz_uint num_syms,tdefl_sym_freq * pSyms0,tdefl_sym_freq * pSyms1)706 static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)
707 {
708     mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
709     tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
710     MZ_CLEAR_OBJ(hist);
711     for (i = 0; i < num_syms; i++)
712     {
713         mz_uint freq = pSyms0[i].m_key;
714         hist[freq & 0xFF]++;
715         hist[256 + ((freq >> 8) & 0xFF)]++;
716     }
717     while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
718         total_passes--;
719     for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
720     {
721         const mz_uint32 *pHist = &hist[pass << 8];
722         mz_uint offsets[256], cur_ofs = 0;
723         for (i = 0; i < 256; i++)
724         {
725             offsets[i] = cur_ofs;
726             cur_ofs += pHist[i];
727         }
728         for (i = 0; i < num_syms; i++)
729             pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
730         {
731             tdefl_sym_freq *t = pCur_syms;
732             pCur_syms = pNew_syms;
733             pNew_syms = t;
734         }
735     }
736     return pCur_syms;
737 }
738 
739 /* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
tdefl_calculate_minimum_redundancy(tdefl_sym_freq * A,int n)740 static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
741 {
742     int root, leaf, next, avbl, used, dpth;
743     if (n == 0)
744         return;
745     else if (n == 1)
746     {
747         A[0].m_key = 1;
748         return;
749     }
750     A[0].m_key += A[1].m_key;
751     root = 0;
752     leaf = 2;
753     for (next = 1; next < n - 1; next++)
754     {
755         if (leaf >= n || A[root].m_key < A[leaf].m_key)
756         {
757             A[next].m_key = A[root].m_key;
758             A[root++].m_key = (mz_uint16)next;
759         }
760         else
761             A[next].m_key = A[leaf++].m_key;
762         if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
763         {
764             A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
765             A[root++].m_key = (mz_uint16)next;
766         }
767         else
768             A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
769     }
770     A[n - 2].m_key = 0;
771     for (next = n - 3; next >= 0; next--)
772         A[next].m_key = A[A[next].m_key].m_key + 1;
773     avbl = 1;
774     used = dpth = 0;
775     root = n - 2;
776     next = n - 1;
777     while (avbl > 0)
778     {
779         while (root >= 0 && (int)A[root].m_key == dpth)
780         {
781             used++;
782             root--;
783         }
784         while (avbl > used)
785         {
786             A[next--].m_key = (mz_uint16)(dpth);
787             avbl--;
788         }
789         avbl = 2 * used;
790         dpth++;
791         used = 0;
792     }
793 }
794 
795 /* Limits canonical Huffman code table's max code size. */
796 enum
797 {
798     TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32
799 };
tdefl_huffman_enforce_max_code_size(int * pNum_codes,int code_list_len,int max_code_size)800 static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
801 {
802     int i;
803     mz_uint32 total = 0;
804     if (code_list_len <= 1)
805         return;
806     for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
807         pNum_codes[max_code_size] += pNum_codes[i];
808     for (i = max_code_size; i > 0; i--)
809         total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
810     while (total != (1UL << max_code_size))
811     {
812         pNum_codes[max_code_size]--;
813         for (i = max_code_size - 1; i > 0; i--)
814             if (pNum_codes[i])
815             {
816                 pNum_codes[i]--;
817                 pNum_codes[i + 1] += 2;
818                 break;
819             }
820         total--;
821     }
822 }
823 
tdefl_optimize_huffman_table(tdefl_compressor * d,int table_num,int table_len,int code_size_limit,int static_table)824 static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
825 {
826     int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
827     mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
828     MZ_CLEAR_OBJ(num_codes);
829     if (static_table)
830     {
831         for (i = 0; i < table_len; i++)
832             num_codes[d->m_huff_code_sizes[table_num][i]]++;
833     }
834     else
835     {
836         tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
837         int num_used_syms = 0;
838         const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
839         for (i = 0; i < table_len; i++)
840             if (pSym_count[i])
841             {
842                 syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
843                 syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
844             }
845 
846         pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
847         tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
848 
849         for (i = 0; i < num_used_syms; i++)
850             num_codes[pSyms[i].m_key]++;
851 
852         tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
853 
854         MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
855         MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
856         for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
857             for (l = num_codes[i]; l > 0; l--)
858                 d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
859     }
860 
861     next_code[1] = 0;
862     for (j = 0, i = 2; i <= code_size_limit; i++)
863         next_code[i] = j = ((j + num_codes[i - 1]) << 1);
864 
865     for (i = 0; i < table_len; i++)
866     {
867         mz_uint rev_code = 0, code, code_size;
868         if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
869             continue;
870         code = next_code[code_size]++;
871         for (l = code_size; l > 0; l--, code >>= 1)
872             rev_code = (rev_code << 1) | (code & 1);
873         d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
874     }
875 }
876 
877 #define TDEFL_PUT_BITS(b, l)                                       \
878     do                                                             \
879     {                                                              \
880         mz_uint bits = b;                                          \
881         mz_uint len = l;                                           \
882         MZ_ASSERT(bits <= ((1U << len) - 1U));                     \
883         d->m_bit_buffer |= (bits << d->m_bits_in);                 \
884         d->m_bits_in += len;                                       \
885         while (d->m_bits_in >= 8)                                  \
886         {                                                          \
887             if (d->m_pOutput_buf < d->m_pOutput_buf_end)           \
888                 *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
889             d->m_bit_buffer >>= 8;                                 \
890             d->m_bits_in -= 8;                                     \
891         }                                                          \
892     }                                                              \
893     MZ_MACRO_END
894 
895 #define TDEFL_RLE_PREV_CODE_SIZE()                                                                                       \
896     {                                                                                                                    \
897         if (rle_repeat_count)                                                                                            \
898         {                                                                                                                \
899             if (rle_repeat_count < 3)                                                                                    \
900             {                                                                                                            \
901                 d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
902                 while (rle_repeat_count--)                                                                               \
903                     packed_code_sizes[num_packed_code_sizes++] = prev_code_size;                                         \
904             }                                                                                                            \
905             else                                                                                                         \
906             {                                                                                                            \
907                 d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);                                        \
908                 packed_code_sizes[num_packed_code_sizes++] = 16;                                                         \
909                 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3);                           \
910             }                                                                                                            \
911             rle_repeat_count = 0;                                                                                        \
912         }                                                                                                                \
913     }
914 
915 #define TDEFL_RLE_ZERO_CODE_SIZE()                                                         \
916     {                                                                                      \
917         if (rle_z_count)                                                                   \
918         {                                                                                  \
919             if (rle_z_count < 3)                                                           \
920             {                                                                              \
921                 d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);  \
922                 while (rle_z_count--)                                                      \
923                     packed_code_sizes[num_packed_code_sizes++] = 0;                        \
924             }                                                                              \
925             else if (rle_z_count <= 10)                                                    \
926             {                                                                              \
927                 d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);          \
928                 packed_code_sizes[num_packed_code_sizes++] = 17;                           \
929                 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3);  \
930             }                                                                              \
931             else                                                                           \
932             {                                                                              \
933                 d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);          \
934                 packed_code_sizes[num_packed_code_sizes++] = 18;                           \
935                 packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
936             }                                                                              \
937             rle_z_count = 0;                                                               \
938         }                                                                                  \
939     }
940 
941 static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
942 
tdefl_start_dynamic_block(tdefl_compressor * d)943 static void tdefl_start_dynamic_block(tdefl_compressor *d)
944 {
945     int num_lit_codes, num_dist_codes, num_bit_lengths;
946     mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
947     mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF;
948 
949     d->m_huff_count[0][256] = 1;
950 
951     tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
952     tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
953 
954     for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
955         if (d->m_huff_code_sizes[0][num_lit_codes - 1])
956             break;
957     for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
958         if (d->m_huff_code_sizes[1][num_dist_codes - 1])
959             break;
960 
961     memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
962     memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
963     total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
964     num_packed_code_sizes = 0;
965     rle_z_count = 0;
966     rle_repeat_count = 0;
967 
968     memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
969     for (i = 0; i < total_code_sizes_to_pack; i++)
970     {
971         mz_uint8 code_size = code_sizes_to_pack[i];
972         if (!code_size)
973         {
974             TDEFL_RLE_PREV_CODE_SIZE();
975             if (++rle_z_count == 138)
976             {
977                 TDEFL_RLE_ZERO_CODE_SIZE();
978             }
979         }
980         else
981         {
982             TDEFL_RLE_ZERO_CODE_SIZE();
983             if (code_size != prev_code_size)
984             {
985                 TDEFL_RLE_PREV_CODE_SIZE();
986                 d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
987                 packed_code_sizes[num_packed_code_sizes++] = code_size;
988             }
989             else if (++rle_repeat_count == 6)
990             {
991                 TDEFL_RLE_PREV_CODE_SIZE();
992             }
993         }
994         prev_code_size = code_size;
995     }
996     if (rle_repeat_count)
997     {
998         TDEFL_RLE_PREV_CODE_SIZE();
999     }
1000     else
1001     {
1002         TDEFL_RLE_ZERO_CODE_SIZE();
1003     }
1004 
1005     tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1006 
1007     TDEFL_PUT_BITS(2, 2);
1008 
1009     TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1010     TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1011 
1012     for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1013         if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1014             break;
1015     num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1016     TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1017     for (i = 0; (int)i < num_bit_lengths; i++)
1018         TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1019 
1020     for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1021     {
1022         mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1023         MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1024         TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1025         if (code >= 16)
1026             TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1027     }
1028 }
1029 
tdefl_start_static_block(tdefl_compressor * d)1030 static void tdefl_start_static_block(tdefl_compressor *d)
1031 {
1032     mz_uint i;
1033     mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1034 
1035     for (i = 0; i <= 143; ++i)
1036         *p++ = 8;
1037     for (; i <= 255; ++i)
1038         *p++ = 9;
1039     for (; i <= 279; ++i)
1040         *p++ = 7;
1041     for (; i <= 287; ++i)
1042         *p++ = 8;
1043 
1044     memset(d->m_huff_code_sizes[1], 5, 32);
1045 
1046     tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1047     tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
1048 
1049     TDEFL_PUT_BITS(1, 2);
1050 }
1051 
1052 static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1053 
1054 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
tdefl_compress_lz_codes(tdefl_compressor * d)1055 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1056 {
1057     mz_uint flags;
1058     mz_uint8 *pLZ_codes;
1059     mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1060     mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1061     mz_uint64 bit_buffer = d->m_bit_buffer;
1062     mz_uint bits_in = d->m_bits_in;
1063 
1064 #define TDEFL_PUT_BITS_FAST(b, l)                    \
1065     {                                                \
1066         bit_buffer |= (((mz_uint64)(b)) << bits_in); \
1067         bits_in += (l);                              \
1068     }
1069 
1070     flags = 1;
1071     for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1072     {
1073         if (flags == 1)
1074             flags = *pLZ_codes++ | 0x100;
1075 
1076         if (flags & 1)
1077         {
1078             mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1079             mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
1080             pLZ_codes += 3;
1081 
1082             MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1083             TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1084             TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1085 
1086             /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
1087             s0 = s_tdefl_small_dist_sym[match_dist & 511];
1088             n0 = s_tdefl_small_dist_extra[match_dist & 511];
1089             s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1090             n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1091             sym = (match_dist < 512) ? s0 : s1;
1092             num_extra_bits = (match_dist < 512) ? n0 : n1;
1093 
1094             MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1095             TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1096             TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1097         }
1098         else
1099         {
1100             mz_uint lit = *pLZ_codes++;
1101             MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1102             TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1103 
1104             if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1105             {
1106                 flags >>= 1;
1107                 lit = *pLZ_codes++;
1108                 MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1109                 TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1110 
1111                 if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1112                 {
1113                     flags >>= 1;
1114                     lit = *pLZ_codes++;
1115                     MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1116                     TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1117                 }
1118             }
1119         }
1120 
1121         if (pOutput_buf >= d->m_pOutput_buf_end)
1122             return MZ_FALSE;
1123 
1124         *(mz_uint64 *)pOutput_buf = bit_buffer;
1125         pOutput_buf += (bits_in >> 3);
1126         bit_buffer >>= (bits_in & ~7);
1127         bits_in &= 7;
1128     }
1129 
1130 #undef TDEFL_PUT_BITS_FAST
1131 
1132     d->m_pOutput_buf = pOutput_buf;
1133     d->m_bits_in = 0;
1134     d->m_bit_buffer = 0;
1135 
1136     while (bits_in)
1137     {
1138         mz_uint32 n = MZ_MIN(bits_in, 16);
1139         TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1140         bit_buffer >>= n;
1141         bits_in -= n;
1142     }
1143 
1144     TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1145 
1146     return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1147 }
1148 #else
tdefl_compress_lz_codes(tdefl_compressor * d)1149 static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1150 {
1151     mz_uint flags;
1152     mz_uint8 *pLZ_codes;
1153 
1154     flags = 1;
1155     for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1156     {
1157         if (flags == 1)
1158             flags = *pLZ_codes++ | 0x100;
1159         if (flags & 1)
1160         {
1161             mz_uint sym, num_extra_bits;
1162             mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1163             pLZ_codes += 3;
1164 
1165             MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1166             TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1167             TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1168 
1169             if (match_dist < 512)
1170             {
1171                 sym = s_tdefl_small_dist_sym[match_dist];
1172                 num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1173             }
1174             else
1175             {
1176                 sym = s_tdefl_large_dist_sym[match_dist >> 8];
1177                 num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1178             }
1179             MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1180             TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1181             TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1182         }
1183         else
1184         {
1185             mz_uint lit = *pLZ_codes++;
1186             MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1187             TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1188         }
1189     }
1190 
1191     TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1192 
1193     return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1194 }
1195 #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */
1196 
tdefl_compress_block(tdefl_compressor * d,mz_bool static_block)1197 static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
1198 {
1199     if (static_block)
1200         tdefl_start_static_block(d);
1201     else
1202         tdefl_start_dynamic_block(d);
1203     return tdefl_compress_lz_codes(d);
1204 }
1205 
tdefl_flush_block(tdefl_compressor * d,int flush)1206 static int tdefl_flush_block(tdefl_compressor *d, int flush)
1207 {
1208     mz_uint saved_bit_buf, saved_bits_in;
1209     mz_uint8 *pSaved_output_buf;
1210     mz_bool comp_block_succeeded = MZ_FALSE;
1211     int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size;
1212     mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf;
1213 
1214     d->m_pOutput_buf = pOutput_buf_start;
1215     d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
1216 
1217     MZ_ASSERT(!d->m_output_flush_remaining);
1218     d->m_output_flush_ofs = 0;
1219     d->m_output_flush_remaining = 0;
1220 
1221     *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
1222     d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1223 
1224     if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1225     {
1226         TDEFL_PUT_BITS(0x78, 8);
1227         TDEFL_PUT_BITS(0x01, 8);
1228     }
1229 
1230     TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1231 
1232     pSaved_output_buf = d->m_pOutput_buf;
1233     saved_bit_buf = d->m_bit_buffer;
1234     saved_bits_in = d->m_bits_in;
1235 
1236     if (!use_raw_block)
1237         comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1238 
1239     /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
1240     if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1241         ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))
1242     {
1243         mz_uint i;
1244         d->m_pOutput_buf = pSaved_output_buf;
1245         d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1246         TDEFL_PUT_BITS(0, 2);
1247         if (d->m_bits_in)
1248         {
1249             TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1250         }
1251         for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1252         {
1253             TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1254         }
1255         for (i = 0; i < d->m_total_lz_bytes; ++i)
1256         {
1257             TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
1258         }
1259     }
1260     /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
1261     else if (!comp_block_succeeded)
1262     {
1263         d->m_pOutput_buf = pSaved_output_buf;
1264         d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1265         tdefl_compress_block(d, MZ_TRUE);
1266     }
1267 
1268     if (flush)
1269     {
1270         if (flush == TDEFL_FINISH)
1271         {
1272             if (d->m_bits_in)
1273             {
1274                 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1275             }
1276             if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
1277             {
1278                 mz_uint i, a = d->m_adler32;
1279                 for (i = 0; i < 4; i++)
1280                 {
1281                     TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1282                     a <<= 8;
1283                 }
1284             }
1285         }
1286         else
1287         {
1288             mz_uint i, z = 0;
1289             TDEFL_PUT_BITS(0, 3);
1290             if (d->m_bits_in)
1291             {
1292                 TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1293             }
1294             for (i = 2; i; --i, z ^= 0xFFFF)
1295             {
1296                 TDEFL_PUT_BITS(z & 0xFFFF, 16);
1297             }
1298         }
1299     }
1300 
1301     MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
1302 
1303     memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1304     memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1305 
1306     d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1307     d->m_pLZ_flags = d->m_lz_code_buf;
1308     d->m_num_flags_left = 8;
1309     d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
1310     d->m_total_lz_bytes = 0;
1311     d->m_block_index++;
1312 
1313     if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1314     {
1315         if (d->m_pPut_buf_func)
1316         {
1317             *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1318             if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1319                 return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
1320         }
1321         else if (pOutput_buf_start == d->m_output_buf)
1322         {
1323             int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1324             memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1325             d->m_out_buf_ofs += bytes_to_copy;
1326             if ((n -= bytes_to_copy) != 0)
1327             {
1328                 d->m_output_flush_ofs = bytes_to_copy;
1329                 d->m_output_flush_remaining = n;
1330             }
1331         }
1332         else
1333         {
1334             d->m_out_buf_ofs += n;
1335         }
1336     }
1337 
1338     return d->m_output_flush_remaining;
1339 }
1340 
1341 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1342 #ifdef MINIZ_UNALIGNED_USE_MEMCPY
TDEFL_READ_UNALIGNED_WORD(const mz_uint8 * p)1343 static inline mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p)
1344 {
1345 	mz_uint16 ret;
1346 	memcpy(&ret, p, sizeof(mz_uint16));
1347 	return ret;
1348 }
TDEFL_READ_UNALIGNED_WORD2(const mz_uint16 * p)1349 static inline mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p)
1350 {
1351 	mz_uint16 ret;
1352 	memcpy(&ret, p, sizeof(mz_uint16));
1353 	return ret;
1354 }
1355 #else
1356 #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
1357 #define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
1358 #endif
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)1359 static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1360 {
1361     mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1362     mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1363     const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
1364     mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);
1365     MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1366     if (max_match_len <= match_len)
1367         return;
1368     for (;;)
1369     {
1370         for (;;)
1371         {
1372             if (--num_probes_left == 0)
1373                 return;
1374 #define TDEFL_PROBE                                                                             \
1375     next_probe_pos = d->m_next[probe_pos];                                                      \
1376     if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1377         return;                                                                                 \
1378     probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                       \
1379     if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01)                \
1380         break;
1381             TDEFL_PROBE;
1382             TDEFL_PROBE;
1383             TDEFL_PROBE;
1384         }
1385         if (!dist)
1386             break;
1387         q = (const mz_uint16 *)(d->m_dict + probe_pos);
1388         if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
1389             continue;
1390         p = s;
1391         probe_len = 32;
1392         do
1393         {
1394         } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1395                  (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1396         if (!probe_len)
1397         {
1398             *pMatch_dist = dist;
1399             *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
1400             break;
1401         }
1402         else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)
1403         {
1404             *pMatch_dist = dist;
1405             if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
1406                 break;
1407             c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1408         }
1409     }
1410 }
1411 #else
tdefl_find_match(tdefl_compressor * d,mz_uint lookahead_pos,mz_uint max_dist,mz_uint max_match_len,mz_uint * pMatch_dist,mz_uint * pMatch_len)1412 static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len)
1413 {
1414     mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1415     mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1416     const mz_uint8 *s = d->m_dict + pos, *p, *q;
1417     mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1418     MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1419     if (max_match_len <= match_len)
1420         return;
1421     for (;;)
1422     {
1423         for (;;)
1424         {
1425             if (--num_probes_left == 0)
1426                 return;
1427 #define TDEFL_PROBE                                                                               \
1428     next_probe_pos = d->m_next[probe_pos];                                                        \
1429     if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))   \
1430         return;                                                                                   \
1431     probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                         \
1432     if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1433         break;
1434             TDEFL_PROBE;
1435             TDEFL_PROBE;
1436             TDEFL_PROBE;
1437         }
1438         if (!dist)
1439             break;
1440         p = s;
1441         q = d->m_dict + probe_pos;
1442         for (probe_len = 0; probe_len < max_match_len; probe_len++)
1443             if (*p++ != *q++)
1444                 break;
1445         if (probe_len > match_len)
1446         {
1447             *pMatch_dist = dist;
1448             if ((*pMatch_len = match_len = probe_len) == max_match_len)
1449                 return;
1450             c0 = d->m_dict[pos + match_len];
1451             c1 = d->m_dict[pos + match_len - 1];
1452         }
1453     }
1454 }
1455 #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
1456 
1457 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
tdefl_compress_fast(tdefl_compressor * d)1458 static mz_bool tdefl_compress_fast(tdefl_compressor *d)
1459 {
1460     /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
1461     mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left;
1462     mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1463     mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1464 
1465     while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1466     {
1467         const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1468         mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1469         mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1470         d->m_src_buf_left -= num_bytes_to_process;
1471         lookahead_size += num_bytes_to_process;
1472 
1473         while (num_bytes_to_process)
1474         {
1475             mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1476             memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1477             if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1478                 memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1479             d->m_pSrc += n;
1480             dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1481             num_bytes_to_process -= n;
1482         }
1483 
1484         dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1485         if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
1486             break;
1487 
1488         while (lookahead_size >= 4)
1489         {
1490             mz_uint cur_match_dist, cur_match_len = 1;
1491             mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1492             mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF;
1493             mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1494             mz_uint probe_pos = d->m_hash[hash];
1495             d->m_hash[hash] = (mz_uint16)lookahead_pos;
1496 
1497             if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram))
1498             {
1499                 const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
1500                 const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
1501                 mz_uint32 probe_len = 32;
1502                 do
1503                 {
1504                 } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1505                          (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1506                 cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
1507                 if (!probe_len)
1508                     cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1509 
1510                 if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
1511                 {
1512                     cur_match_len = 1;
1513                     *pLZ_code_buf++ = (mz_uint8)first_trigram;
1514                     *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1515                     d->m_huff_count[0][(mz_uint8)first_trigram]++;
1516                 }
1517                 else
1518                 {
1519                     mz_uint32 s0, s1;
1520                     cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1521 
1522                     MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1523 
1524                     cur_match_dist--;
1525 
1526                     pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1527                     *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1528                     pLZ_code_buf += 3;
1529                     *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1530 
1531                     s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1532                     s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1533                     d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1534 
1535                     d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1536                 }
1537             }
1538             else
1539             {
1540                 *pLZ_code_buf++ = (mz_uint8)first_trigram;
1541                 *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1542                 d->m_huff_count[0][(mz_uint8)first_trigram]++;
1543             }
1544 
1545             if (--num_flags_left == 0)
1546             {
1547                 num_flags_left = 8;
1548                 pLZ_flags = pLZ_code_buf++;
1549             }
1550 
1551             total_lz_bytes += cur_match_len;
1552             lookahead_pos += cur_match_len;
1553             dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
1554             cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1555             MZ_ASSERT(lookahead_size >= cur_match_len);
1556             lookahead_size -= cur_match_len;
1557 
1558             if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1559             {
1560                 int n;
1561                 d->m_lookahead_pos = lookahead_pos;
1562                 d->m_lookahead_size = lookahead_size;
1563                 d->m_dict_size = dict_size;
1564                 d->m_total_lz_bytes = total_lz_bytes;
1565                 d->m_pLZ_code_buf = pLZ_code_buf;
1566                 d->m_pLZ_flags = pLZ_flags;
1567                 d->m_num_flags_left = num_flags_left;
1568                 if ((n = tdefl_flush_block(d, 0)) != 0)
1569                     return (n < 0) ? MZ_FALSE : MZ_TRUE;
1570                 total_lz_bytes = d->m_total_lz_bytes;
1571                 pLZ_code_buf = d->m_pLZ_code_buf;
1572                 pLZ_flags = d->m_pLZ_flags;
1573                 num_flags_left = d->m_num_flags_left;
1574             }
1575         }
1576 
1577         while (lookahead_size)
1578         {
1579             mz_uint8 lit = d->m_dict[cur_pos];
1580 
1581             total_lz_bytes++;
1582             *pLZ_code_buf++ = lit;
1583             *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1584             if (--num_flags_left == 0)
1585             {
1586                 num_flags_left = 8;
1587                 pLZ_flags = pLZ_code_buf++;
1588             }
1589 
1590             d->m_huff_count[0][lit]++;
1591 
1592             lookahead_pos++;
1593             dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
1594             cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1595             lookahead_size--;
1596 
1597             if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1598             {
1599                 int n;
1600                 d->m_lookahead_pos = lookahead_pos;
1601                 d->m_lookahead_size = lookahead_size;
1602                 d->m_dict_size = dict_size;
1603                 d->m_total_lz_bytes = total_lz_bytes;
1604                 d->m_pLZ_code_buf = pLZ_code_buf;
1605                 d->m_pLZ_flags = pLZ_flags;
1606                 d->m_num_flags_left = num_flags_left;
1607                 if ((n = tdefl_flush_block(d, 0)) != 0)
1608                     return (n < 0) ? MZ_FALSE : MZ_TRUE;
1609                 total_lz_bytes = d->m_total_lz_bytes;
1610                 pLZ_code_buf = d->m_pLZ_code_buf;
1611                 pLZ_flags = d->m_pLZ_flags;
1612                 num_flags_left = d->m_num_flags_left;
1613             }
1614         }
1615     }
1616 
1617     d->m_lookahead_pos = lookahead_pos;
1618     d->m_lookahead_size = lookahead_size;
1619     d->m_dict_size = dict_size;
1620     d->m_total_lz_bytes = total_lz_bytes;
1621     d->m_pLZ_code_buf = pLZ_code_buf;
1622     d->m_pLZ_flags = pLZ_flags;
1623     d->m_num_flags_left = num_flags_left;
1624     return MZ_TRUE;
1625 }
1626 #endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1627 
tdefl_record_literal(tdefl_compressor * d,mz_uint8 lit)1628 static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
1629 {
1630     d->m_total_lz_bytes++;
1631     *d->m_pLZ_code_buf++ = lit;
1632     *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1633     if (--d->m_num_flags_left == 0)
1634     {
1635         d->m_num_flags_left = 8;
1636         d->m_pLZ_flags = d->m_pLZ_code_buf++;
1637     }
1638     d->m_huff_count[0][lit]++;
1639 }
1640 
tdefl_record_match(tdefl_compressor * d,mz_uint match_len,mz_uint match_dist)1641 static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
1642 {
1643     mz_uint32 s0, s1;
1644 
1645     MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1646 
1647     d->m_total_lz_bytes += match_len;
1648 
1649     d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1650 
1651     match_dist -= 1;
1652     d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1653     d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1654     d->m_pLZ_code_buf += 3;
1655 
1656     *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1657     if (--d->m_num_flags_left == 0)
1658     {
1659         d->m_num_flags_left = 8;
1660         d->m_pLZ_flags = d->m_pLZ_code_buf++;
1661     }
1662 
1663     s0 = s_tdefl_small_dist_sym[match_dist & 511];
1664     s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1665     d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1666 
1667     if (match_len >= TDEFL_MIN_MATCH_LEN)
1668         d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1669 }
1670 
tdefl_compress_normal(tdefl_compressor * d)1671 static mz_bool tdefl_compress_normal(tdefl_compressor *d)
1672 {
1673     const mz_uint8 *pSrc = d->m_pSrc;
1674     size_t src_buf_left = d->m_src_buf_left;
1675     tdefl_flush flush = d->m_flush;
1676 
1677     while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1678     {
1679         mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1680         /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */
1681         if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1682         {
1683             mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2;
1684             mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK];
1685             mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1686             const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
1687             src_buf_left -= num_bytes_to_process;
1688             d->m_lookahead_size += num_bytes_to_process;
1689             while (pSrc != pSrc_end)
1690             {
1691                 mz_uint8 c = *pSrc++;
1692                 d->m_dict[dst_pos] = c;
1693                 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1694                     d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1695                 hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1696                 d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1697                 d->m_hash[hash] = (mz_uint16)(ins_pos);
1698                 dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1699                 ins_pos++;
1700             }
1701         }
1702         else
1703         {
1704             while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1705             {
1706                 mz_uint8 c = *pSrc++;
1707                 mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1708                 src_buf_left--;
1709                 d->m_dict[dst_pos] = c;
1710                 if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1711                     d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1712                 if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
1713                 {
1714                     mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1715                     mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^ (d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1716                     d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1717                     d->m_hash[hash] = (mz_uint16)(ins_pos);
1718                 }
1719             }
1720         }
1721         d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
1722         if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1723             break;
1724 
1725         /* Simple lazy/greedy parsing state machine. */
1726         len_to_move = 1;
1727         cur_match_dist = 0;
1728         cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1729         cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1730         if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
1731         {
1732             if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1733             {
1734                 mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1735                 cur_match_len = 0;
1736                 while (cur_match_len < d->m_lookahead_size)
1737                 {
1738                     if (d->m_dict[cur_pos + cur_match_len] != c)
1739                         break;
1740                     cur_match_len++;
1741                 }
1742                 if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1743                     cur_match_len = 0;
1744                 else
1745                     cur_match_dist = 1;
1746             }
1747         }
1748         else
1749         {
1750             tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1751         }
1752         if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5)))
1753         {
1754             cur_match_dist = cur_match_len = 0;
1755         }
1756         if (d->m_saved_match_len)
1757         {
1758             if (cur_match_len > d->m_saved_match_len)
1759             {
1760                 tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
1761                 if (cur_match_len >= 128)
1762                 {
1763                     tdefl_record_match(d, cur_match_len, cur_match_dist);
1764                     d->m_saved_match_len = 0;
1765                     len_to_move = cur_match_len;
1766                 }
1767                 else
1768                 {
1769                     d->m_saved_lit = d->m_dict[cur_pos];
1770                     d->m_saved_match_dist = cur_match_dist;
1771                     d->m_saved_match_len = cur_match_len;
1772                 }
1773             }
1774             else
1775             {
1776                 tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
1777                 len_to_move = d->m_saved_match_len - 1;
1778                 d->m_saved_match_len = 0;
1779             }
1780         }
1781         else if (!cur_match_dist)
1782             tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1783         else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1784         {
1785             tdefl_record_match(d, cur_match_len, cur_match_dist);
1786             len_to_move = cur_match_len;
1787         }
1788         else
1789         {
1790             d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
1791             d->m_saved_match_dist = cur_match_dist;
1792             d->m_saved_match_len = cur_match_len;
1793         }
1794         /* Move the lookahead forward by len_to_move bytes. */
1795         d->m_lookahead_pos += len_to_move;
1796         MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1797         d->m_lookahead_size -= len_to_move;
1798         d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
1799         /* Check if it's time to flush the current LZ codes to the internal output buffer. */
1800         if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
1801             ((d->m_total_lz_bytes > 31 * 1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))))
1802         {
1803             int n;
1804             d->m_pSrc = pSrc;
1805             d->m_src_buf_left = src_buf_left;
1806             if ((n = tdefl_flush_block(d, 0)) != 0)
1807                 return (n < 0) ? MZ_FALSE : MZ_TRUE;
1808         }
1809     }
1810 
1811     d->m_pSrc = pSrc;
1812     d->m_src_buf_left = src_buf_left;
1813     return MZ_TRUE;
1814 }
1815 
tdefl_flush_output_buffer(tdefl_compressor * d)1816 static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
1817 {
1818     if (d->m_pIn_buf_size)
1819     {
1820         *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1821     }
1822 
1823     if (d->m_pOut_buf_size)
1824     {
1825         size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
1826         memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1827         d->m_output_flush_ofs += (mz_uint)n;
1828         d->m_output_flush_remaining -= (mz_uint)n;
1829         d->m_out_buf_ofs += n;
1830 
1831         *d->m_pOut_buf_size = d->m_out_buf_ofs;
1832     }
1833 
1834     return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
1835 }
1836 
tdefl_compress(tdefl_compressor * d,const void * pIn_buf,size_t * pIn_buf_size,void * pOut_buf,size_t * pOut_buf_size,tdefl_flush flush)1837 tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush)
1838 {
1839     if (!d)
1840     {
1841         if (pIn_buf_size)
1842             *pIn_buf_size = 0;
1843         if (pOut_buf_size)
1844             *pOut_buf_size = 0;
1845         return TDEFL_STATUS_BAD_PARAM;
1846     }
1847 
1848     d->m_pIn_buf = pIn_buf;
1849     d->m_pIn_buf_size = pIn_buf_size;
1850     d->m_pOut_buf = pOut_buf;
1851     d->m_pOut_buf_size = pOut_buf_size;
1852     d->m_pSrc = (const mz_uint8 *)(pIn_buf);
1853     d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1854     d->m_out_buf_ofs = 0;
1855     d->m_flush = flush;
1856 
1857     if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1858         (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
1859     {
1860         if (pIn_buf_size)
1861             *pIn_buf_size = 0;
1862         if (pOut_buf_size)
1863             *pOut_buf_size = 0;
1864         return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
1865     }
1866     d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1867 
1868     if ((d->m_output_flush_remaining) || (d->m_finished))
1869         return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1870 
1871 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1872     if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1873         ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1874         ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
1875     {
1876         if (!tdefl_compress_fast(d))
1877             return d->m_prev_return_status;
1878     }
1879     else
1880 #endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1881     {
1882         if (!tdefl_compress_normal(d))
1883             return d->m_prev_return_status;
1884     }
1885 
1886     if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1887         d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
1888 
1889     if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1890     {
1891         if (tdefl_flush_block(d, flush) < 0)
1892             return d->m_prev_return_status;
1893         d->m_finished = (flush == TDEFL_FINISH);
1894         if (flush == TDEFL_FULL_FLUSH)
1895         {
1896             MZ_CLEAR_OBJ(d->m_hash);
1897             MZ_CLEAR_OBJ(d->m_next);
1898             d->m_dict_size = 0;
1899         }
1900     }
1901 
1902     return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1903 }
1904 
tdefl_compress_buffer(tdefl_compressor * d,const void * pIn_buf,size_t in_buf_size,tdefl_flush flush)1905 tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1906 {
1907     MZ_ASSERT(d->m_pPut_buf_func);
1908     return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1909 }
1910 
tdefl_init(tdefl_compressor * d,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)1911 tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1912 {
1913     d->m_pPut_buf_func = pPut_buf_func;
1914     d->m_pPut_buf_user = pPut_buf_user;
1915     d->m_flags = (mz_uint)(flags);
1916     d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
1917     d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
1918     d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
1919     if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
1920         MZ_CLEAR_OBJ(d->m_hash);
1921     d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0;
1922     d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0;
1923     d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1924     d->m_pLZ_flags = d->m_lz_code_buf;
1925     d->m_num_flags_left = 8;
1926     d->m_pOutput_buf = d->m_output_buf;
1927     d->m_pOutput_buf_end = d->m_output_buf;
1928     d->m_prev_return_status = TDEFL_STATUS_OKAY;
1929     d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
1930     d->m_adler32 = 1;
1931     d->m_pIn_buf = NULL;
1932     d->m_pOut_buf = NULL;
1933     d->m_pIn_buf_size = NULL;
1934     d->m_pOut_buf_size = NULL;
1935     d->m_flush = TDEFL_NO_FLUSH;
1936     d->m_pSrc = NULL;
1937     d->m_src_buf_left = 0;
1938     d->m_out_buf_ofs = 0;
1939     if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
1940         MZ_CLEAR_OBJ(d->m_dict);
1941     memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1942     memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1943     return TDEFL_STATUS_OKAY;
1944 }
1945 
tdefl_get_prev_return_status(tdefl_compressor * d)1946 tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
1947 {
1948     return d->m_prev_return_status;
1949 }
1950 
tdefl_get_adler32(tdefl_compressor * d)1951 mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
1952 {
1953     return d->m_adler32;
1954 }
1955 
tdefl_compress_mem_to_output(const void * pBuf,size_t buf_len,tdefl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)1956 mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1957 {
1958     tdefl_compressor *pComp;
1959     mz_bool succeeded;
1960     if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
1961         return MZ_FALSE;
1962     pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
1963     if (!pComp)
1964         return MZ_FALSE;
1965     succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
1966     succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
1967     MZ_FREE(pComp);
1968     return succeeded;
1969 }
1970 
1971 typedef struct
1972 {
1973     size_t m_size, m_capacity;
1974     mz_uint8 *m_pBuf;
1975     mz_bool m_expandable;
1976 } tdefl_output_buffer;
1977 
tdefl_output_buffer_putter(const void * pBuf,int len,void * pUser)1978 static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
1979 {
1980     tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
1981     size_t new_size = p->m_size + len;
1982     if (new_size > p->m_capacity)
1983     {
1984         size_t new_capacity = p->m_capacity;
1985         mz_uint8 *pNew_buf;
1986         if (!p->m_expandable)
1987             return MZ_FALSE;
1988         do
1989         {
1990             new_capacity = MZ_MAX(128U, new_capacity << 1U);
1991         } while (new_size > new_capacity);
1992         pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
1993         if (!pNew_buf)
1994             return MZ_FALSE;
1995         p->m_pBuf = pNew_buf;
1996         p->m_capacity = new_capacity;
1997     }
1998     memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
1999     p->m_size = new_size;
2000     return MZ_TRUE;
2001 }
2002 
tdefl_compress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2003 void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2004 {
2005     tdefl_output_buffer out_buf;
2006     MZ_CLEAR_OBJ(out_buf);
2007     if (!pOut_len)
2008         return MZ_FALSE;
2009     else
2010         *pOut_len = 0;
2011     out_buf.m_expandable = MZ_TRUE;
2012     if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2013         return NULL;
2014     *pOut_len = out_buf.m_size;
2015     return out_buf.m_pBuf;
2016 }
2017 
tdefl_compress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)2018 size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2019 {
2020     tdefl_output_buffer out_buf;
2021     MZ_CLEAR_OBJ(out_buf);
2022     if (!pOut_buf)
2023         return 0;
2024     out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2025     out_buf.m_capacity = out_buf_len;
2026     if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2027         return 0;
2028     return out_buf.m_size;
2029 }
2030 
2031 static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2032 
2033 /* level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). */
tdefl_create_comp_flags_from_zip_params(int level,int window_bits,int strategy)2034 mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2035 {
2036     mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2037     if (window_bits > 0)
2038         comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2039 
2040     if (!level)
2041         comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2042     else if (strategy == MZ_FILTERED)
2043         comp_flags |= TDEFL_FILTER_MATCHES;
2044     else if (strategy == MZ_HUFFMAN_ONLY)
2045         comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2046     else if (strategy == MZ_FIXED)
2047         comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2048     else if (strategy == MZ_RLE)
2049         comp_flags |= TDEFL_RLE_MATCHES;
2050 
2051     return comp_flags;
2052 }
2053 
2054 #ifdef _MSC_VER
2055 #pragma warning(push)
2056 #pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */
2057 #endif
2058 
2059 /* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2060  http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2061  This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */
tdefl_write_image_to_png_file_in_memory_ex(const void * pImage,int w,int h,int num_chans,size_t * pLen_out,mz_uint level,mz_bool flip)2062 void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip)
2063 {
2064     /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
2065     static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2066     tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2067     tdefl_output_buffer out_buf;
2068     int i, bpl = w * num_chans, y, z;
2069     mz_uint32 c;
2070     *pLen_out = 0;
2071     if (!pComp)
2072         return NULL;
2073     MZ_CLEAR_OBJ(out_buf);
2074     out_buf.m_expandable = MZ_TRUE;
2075     out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2076     if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2077     {
2078         MZ_FREE(pComp);
2079         return NULL;
2080     }
2081     /* write dummy header */
2082     for (z = 41; z; --z)
2083         tdefl_output_buffer_putter(&z, 1, &out_buf);
2084     /* compress image data */
2085     tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2086     for (y = 0; y < h; ++y)
2087     {
2088         tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
2089         tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2090     }
2091     if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
2092     {
2093         MZ_FREE(pComp);
2094         MZ_FREE(out_buf.m_pBuf);
2095         return NULL;
2096     }
2097     /* write real header */
2098     *pLen_out = out_buf.m_size - 41;
2099     {
2100         static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2101         mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2102                                 0x0a, 0x1a, 0x0a, 0x00, 0x00,
2103                                 0x00, 0x0d, 0x49, 0x48, 0x44,
2104                                 0x52, 0x00, 0x00, 0x00, 0x00,
2105                                 0x00, 0x00, 0x00, 0x00, 0x08,
2106                                 0x00, 0x00, 0x00, 0x00, 0x00,
2107                                 0x00, 0x00, 0x00, 0x00, 0x00,
2108                                 0x00, 0x00, 0x49, 0x44, 0x41,
2109                                 0x54 };
2110         pnghdr[18] = (mz_uint8)(w >> 8);
2111         pnghdr[19] = (mz_uint8)w;
2112         pnghdr[22] = (mz_uint8)(h >> 8);
2113         pnghdr[23] = (mz_uint8)h;
2114         pnghdr[25] = chans[num_chans];
2115         pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2116         pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2117         pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2118         pnghdr[36] = (mz_uint8)*pLen_out;
2119         c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2120         for (i = 0; i < 4; ++i, c <<= 8)
2121             ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2122         memcpy(out_buf.m_pBuf, pnghdr, 41);
2123     }
2124     /* write footer (IDAT CRC-32, followed by IEND chunk) */
2125     if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
2126     {
2127         *pLen_out = 0;
2128         MZ_FREE(pComp);
2129         MZ_FREE(out_buf.m_pBuf);
2130         return NULL;
2131     }
2132     c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2133     for (i = 0; i < 4; ++i, c <<= 8)
2134         (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
2135     /* compute final size of file, grab compressed data buffer and return */
2136     *pLen_out += 57;
2137     MZ_FREE(pComp);
2138     return out_buf.m_pBuf;
2139 }
tdefl_write_image_to_png_file_in_memory(const void * pImage,int w,int h,int num_chans,size_t * pLen_out)2140 void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2141 {
2142     /* Level 6 corresponds to TDEFL_DEFAULT_MAX_PROBES or MZ_DEFAULT_LEVEL (but we can't depend on MZ_DEFAULT_LEVEL being available in case the zlib API's where #defined out) */
2143     return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2144 }
2145 
2146 /* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */
2147 /* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
2148 /* structure size and allocation mechanism. */
tdefl_compressor_alloc()2149 tdefl_compressor *tdefl_compressor_alloc()
2150 {
2151     return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2152 }
2153 
tdefl_compressor_free(tdefl_compressor * pComp)2154 void tdefl_compressor_free(tdefl_compressor *pComp)
2155 {
2156     MZ_FREE(pComp);
2157 }
2158 
2159 #ifdef _MSC_VER
2160 #pragma warning(pop)
2161 #endif
2162 
2163 #ifdef __cplusplus
2164 }
2165 #endif
2166 /**************************************************************************
2167  *
2168  * Copyright 2013-2014 RAD Game Tools and Valve Software
2169  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2170  * All Rights Reserved.
2171  *
2172  * Permission is hereby granted, free of charge, to any person obtaining a copy
2173  * of this software and associated documentation files (the "Software"), to deal
2174  * in the Software without restriction, including without limitation the rights
2175  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2176  * copies of the Software, and to permit persons to whom the Software is
2177  * furnished to do so, subject to the following conditions:
2178  *
2179  * The above copyright notice and this permission notice shall be included in
2180  * all copies or substantial portions of the Software.
2181  *
2182  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2183  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2184  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2185  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2186  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2187  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2188  * THE SOFTWARE.
2189  *
2190  **************************************************************************/
2191 
2192 
2193 
2194 #ifdef __cplusplus
2195 extern "C" {
2196 #endif
2197 
2198 /* ------------------- Low-level Decompression (completely independent from all compression API's) */
2199 
2200 #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2201 #define TINFL_MEMSET(p, c, l) memset(p, c, l)
2202 
2203 #define TINFL_CR_BEGIN  \
2204     switch (r->m_state) \
2205     {                   \
2206         case 0:
2207 #define TINFL_CR_RETURN(state_index, result) \
2208     do                                       \
2209     {                                        \
2210         status = result;                     \
2211         r->m_state = state_index;            \
2212         goto common_exit;                    \
2213         case state_index:;                   \
2214     }                                        \
2215     MZ_MACRO_END
2216 #define TINFL_CR_RETURN_FOREVER(state_index, result) \
2217     do                                               \
2218     {                                                \
2219         for (;;)                                     \
2220         {                                            \
2221             TINFL_CR_RETURN(state_index, result);    \
2222         }                                            \
2223     }                                                \
2224     MZ_MACRO_END
2225 #define TINFL_CR_FINISH }
2226 
2227 #define TINFL_GET_BYTE(state_index, c)                                                                                                                           \
2228     do                                                                                                                                                           \
2229     {                                                                                                                                                            \
2230         while (pIn_buf_cur >= pIn_buf_end)                                                                                                                       \
2231         {                                                                                                                                                        \
2232             TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2233         }                                                                                                                                                        \
2234         c = *pIn_buf_cur++;                                                                                                                                      \
2235     }                                                                                                                                                            \
2236     MZ_MACRO_END
2237 
2238 #define TINFL_NEED_BITS(state_index, n)                \
2239     do                                                 \
2240     {                                                  \
2241         mz_uint c;                                     \
2242         TINFL_GET_BYTE(state_index, c);                \
2243         bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2244         num_bits += 8;                                 \
2245     } while (num_bits < (mz_uint)(n))
2246 #define TINFL_SKIP_BITS(state_index, n)      \
2247     do                                       \
2248     {                                        \
2249         if (num_bits < (mz_uint)(n))         \
2250         {                                    \
2251             TINFL_NEED_BITS(state_index, n); \
2252         }                                    \
2253         bit_buf >>= (n);                     \
2254         num_bits -= (n);                     \
2255     }                                        \
2256     MZ_MACRO_END
2257 #define TINFL_GET_BITS(state_index, b, n)    \
2258     do                                       \
2259     {                                        \
2260         if (num_bits < (mz_uint)(n))         \
2261         {                                    \
2262             TINFL_NEED_BITS(state_index, n); \
2263         }                                    \
2264         b = bit_buf & ((1 << (n)) - 1);      \
2265         bit_buf >>= (n);                     \
2266         num_bits -= (n);                     \
2267     }                                        \
2268     MZ_MACRO_END
2269 
2270 /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
2271 /* 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 */
2272 /* 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 */
2273 /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
2274 #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \
2275     do                                                                         \
2276     {                                                                          \
2277         temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];     \
2278         if (temp >= 0)                                                         \
2279         {                                                                      \
2280             code_len = temp >> 9;                                              \
2281             if ((code_len) && (num_bits >= code_len))                          \
2282                 break;                                                         \
2283         }                                                                      \
2284         else if (num_bits > TINFL_FAST_LOOKUP_BITS)                            \
2285         {                                                                      \
2286             code_len = TINFL_FAST_LOOKUP_BITS;                                 \
2287             do                                                                 \
2288             {                                                                  \
2289                 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2290             } while ((temp < 0) && (num_bits >= (code_len + 1)));              \
2291             if (temp >= 0)                                                     \
2292                 break;                                                         \
2293         }                                                                      \
2294         TINFL_GET_BYTE(state_index, c);                                        \
2295         bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                         \
2296         num_bits += 8;                                                         \
2297     } while (num_bits < 15);
2298 
2299 /* 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 */
2300 /* 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 */
2301 /* 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. */
2302 /* The slow path is only executed at the very end of the input buffer. */
2303 /* 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 */
2304 /* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
2305 #define TINFL_HUFF_DECODE(state_index, sym, pHuff)                                                                                  \
2306     do                                                                                                                              \
2307     {                                                                                                                               \
2308         int temp;                                                                                                                   \
2309         mz_uint code_len, c;                                                                                                        \
2310         if (num_bits < 15)                                                                                                          \
2311         {                                                                                                                           \
2312             if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \
2313             {                                                                                                                       \
2314                 TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                                                                         \
2315             }                                                                                                                       \
2316             else                                                                                                                    \
2317             {                                                                                                                       \
2318                 bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2319                 pIn_buf_cur += 2;                                                                                                   \
2320                 num_bits += 16;                                                                                                     \
2321             }                                                                                                                       \
2322         }                                                                                                                           \
2323         if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                               \
2324             code_len = temp >> 9, temp &= 511;                                                                                      \
2325         else                                                                                                                        \
2326         {                                                                                                                           \
2327             code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \
2328             do                                                                                                                      \
2329             {                                                                                                                       \
2330                 temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];                                                      \
2331             } while (temp < 0);                                                                                                     \
2332         }                                                                                                                           \
2333         sym = temp;                                                                                                                 \
2334         bit_buf >>= code_len;                                                                                                       \
2335         num_bits -= code_len;                                                                                                       \
2336     }                                                                                                                               \
2337     MZ_MACRO_END
2338 
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)2339 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)
2340 {
2341     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 };
2342     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 };
2343     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 };
2344     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 };
2345     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 };
2346     static const int s_min_table_sizes[3] = { 257, 1, 4 };
2347 
2348     tinfl_status status = TINFL_STATUS_FAILED;
2349     mz_uint32 num_bits, dist, counter, num_extra;
2350     tinfl_bit_buf_t bit_buf;
2351     const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2352     mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
2353     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;
2354 
2355     /* 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). */
2356     if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2357     {
2358         *pIn_buf_size = *pOut_buf_size = 0;
2359         return TINFL_STATUS_BAD_PARAM;
2360     }
2361 
2362     num_bits = r->m_num_bits;
2363     bit_buf = r->m_bit_buf;
2364     dist = r->m_dist;
2365     counter = r->m_counter;
2366     num_extra = r->m_num_extra;
2367     dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2368     TINFL_CR_BEGIN
2369 
2370     bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2371     r->m_z_adler32 = r->m_check_adler32 = 1;
2372     if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2373     {
2374         TINFL_GET_BYTE(1, r->m_zhdr0);
2375         TINFL_GET_BYTE(2, r->m_zhdr1);
2376         counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2377         if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2378             counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2379         if (counter)
2380         {
2381             TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2382         }
2383     }
2384 
2385     do
2386     {
2387         TINFL_GET_BITS(3, r->m_final, 3);
2388         r->m_type = r->m_final >> 1;
2389         if (r->m_type == 0)
2390         {
2391             TINFL_SKIP_BITS(5, num_bits & 7);
2392             for (counter = 0; counter < 4; ++counter)
2393             {
2394                 if (num_bits)
2395                     TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2396                 else
2397                     TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2398             }
2399             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))))
2400             {
2401                 TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2402             }
2403             while ((counter) && (num_bits))
2404             {
2405                 TINFL_GET_BITS(51, dist, 8);
2406                 while (pOut_buf_cur >= pOut_buf_end)
2407                 {
2408                     TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2409                 }
2410                 *pOut_buf_cur++ = (mz_uint8)dist;
2411                 counter--;
2412             }
2413             while (counter)
2414             {
2415                 size_t n;
2416                 while (pOut_buf_cur >= pOut_buf_end)
2417                 {
2418                     TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2419                 }
2420                 while (pIn_buf_cur >= pIn_buf_end)
2421                 {
2422                     TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
2423                 }
2424                 n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2425                 TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2426                 pIn_buf_cur += n;
2427                 pOut_buf_cur += n;
2428                 counter -= (mz_uint)n;
2429             }
2430         }
2431         else if (r->m_type == 3)
2432         {
2433             TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2434         }
2435         else
2436         {
2437             if (r->m_type == 1)
2438             {
2439                 mz_uint8 *p = r->m_tables[0].m_code_size;
2440                 mz_uint i;
2441                 r->m_table_sizes[0] = 288;
2442                 r->m_table_sizes[1] = 32;
2443                 TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2444                 for (i = 0; i <= 143; ++i)
2445                     *p++ = 8;
2446                 for (; i <= 255; ++i)
2447                     *p++ = 9;
2448                 for (; i <= 279; ++i)
2449                     *p++ = 7;
2450                 for (; i <= 287; ++i)
2451                     *p++ = 8;
2452             }
2453             else
2454             {
2455                 for (counter = 0; counter < 3; counter++)
2456                 {
2457                     TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2458                     r->m_table_sizes[counter] += s_min_table_sizes[counter];
2459                 }
2460                 MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2461                 for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2462                 {
2463                     mz_uint s;
2464                     TINFL_GET_BITS(14, s, 3);
2465                     r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2466                 }
2467                 r->m_table_sizes[2] = 19;
2468             }
2469             for (; (int)r->m_type >= 0; r->m_type--)
2470             {
2471                 int tree_next, tree_cur;
2472                 tinfl_huff_table *pTable;
2473                 mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2474                 pTable = &r->m_tables[r->m_type];
2475                 MZ_CLEAR_OBJ(total_syms);
2476                 MZ_CLEAR_OBJ(pTable->m_look_up);
2477                 MZ_CLEAR_OBJ(pTable->m_tree);
2478                 for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2479                     total_syms[pTable->m_code_size[i]]++;
2480                 used_syms = 0, total = 0;
2481                 next_code[0] = next_code[1] = 0;
2482                 for (i = 1; i <= 15; ++i)
2483                 {
2484                     used_syms += total_syms[i];
2485                     next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2486                 }
2487                 if ((65536 != total) && (used_syms > 1))
2488                 {
2489                     TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2490                 }
2491                 for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2492                 {
2493                     mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
2494                     if (!code_size)
2495                         continue;
2496                     cur_code = next_code[code_size]++;
2497                     for (l = code_size; l > 0; l--, cur_code >>= 1)
2498                         rev_code = (rev_code << 1) | (cur_code & 1);
2499                     if (code_size <= TINFL_FAST_LOOKUP_BITS)
2500                     {
2501                         mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2502                         while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2503                         {
2504                             pTable->m_look_up[rev_code] = k;
2505                             rev_code += (1 << code_size);
2506                         }
2507                         continue;
2508                     }
2509                     if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2510                     {
2511                         pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2512                         tree_cur = tree_next;
2513                         tree_next -= 2;
2514                     }
2515                     rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2516                     for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2517                     {
2518                         tree_cur -= ((rev_code >>= 1) & 1);
2519                         if (!pTable->m_tree[-tree_cur - 1])
2520                         {
2521                             pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2522                             tree_cur = tree_next;
2523                             tree_next -= 2;
2524                         }
2525                         else
2526                             tree_cur = pTable->m_tree[-tree_cur - 1];
2527                     }
2528                     tree_cur -= ((rev_code >>= 1) & 1);
2529                     pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2530                 }
2531                 if (r->m_type == 2)
2532                 {
2533                     for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2534                     {
2535                         mz_uint s;
2536                         TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2537                         if (dist < 16)
2538                         {
2539                             r->m_len_codes[counter++] = (mz_uint8)dist;
2540                             continue;
2541                         }
2542                         if ((dist == 16) && (!counter))
2543                         {
2544                             TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2545                         }
2546                         num_extra = "\02\03\07"[dist - 16];
2547                         TINFL_GET_BITS(18, s, num_extra);
2548                         s += "\03\03\013"[dist - 16];
2549                         TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2550                         counter += s;
2551                     }
2552                     if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2553                     {
2554                         TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2555                     }
2556                     TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
2557                     TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
2558                 }
2559             }
2560             for (;;)
2561             {
2562                 mz_uint8 *pSrc;
2563                 for (;;)
2564                 {
2565                     if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2566                     {
2567                         TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2568                         if (counter >= 256)
2569                             break;
2570                         while (pOut_buf_cur >= pOut_buf_end)
2571                         {
2572                             TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2573                         }
2574                         *pOut_buf_cur++ = (mz_uint8)counter;
2575                     }
2576                     else
2577                     {
2578                         int sym2;
2579                         mz_uint code_len;
2580 #if TINFL_USE_64BIT_BITBUF
2581                         if (num_bits < 30)
2582                         {
2583                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2584                             pIn_buf_cur += 4;
2585                             num_bits += 32;
2586                         }
2587 #else
2588                         if (num_bits < 15)
2589                         {
2590                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2591                             pIn_buf_cur += 2;
2592                             num_bits += 16;
2593                         }
2594 #endif
2595                         if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2596                             code_len = sym2 >> 9;
2597                         else
2598                         {
2599                             code_len = TINFL_FAST_LOOKUP_BITS;
2600                             do
2601                             {
2602                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2603                             } while (sym2 < 0);
2604                         }
2605                         counter = sym2;
2606                         bit_buf >>= code_len;
2607                         num_bits -= code_len;
2608                         if (counter & 256)
2609                             break;
2610 
2611 #if !TINFL_USE_64BIT_BITBUF
2612                         if (num_bits < 15)
2613                         {
2614                             bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2615                             pIn_buf_cur += 2;
2616                             num_bits += 16;
2617                         }
2618 #endif
2619                         if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2620                             code_len = sym2 >> 9;
2621                         else
2622                         {
2623                             code_len = TINFL_FAST_LOOKUP_BITS;
2624                             do
2625                             {
2626                                 sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2627                             } while (sym2 < 0);
2628                         }
2629                         bit_buf >>= code_len;
2630                         num_bits -= code_len;
2631 
2632                         pOut_buf_cur[0] = (mz_uint8)counter;
2633                         if (sym2 & 256)
2634                         {
2635                             pOut_buf_cur++;
2636                             counter = sym2;
2637                             break;
2638                         }
2639                         pOut_buf_cur[1] = (mz_uint8)sym2;
2640                         pOut_buf_cur += 2;
2641                     }
2642                 }
2643                 if ((counter &= 511) == 256)
2644                     break;
2645 
2646                 num_extra = s_length_extra[counter - 257];
2647                 counter = s_length_base[counter - 257];
2648                 if (num_extra)
2649                 {
2650                     mz_uint extra_bits;
2651                     TINFL_GET_BITS(25, extra_bits, num_extra);
2652                     counter += extra_bits;
2653                 }
2654 
2655                 TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2656                 num_extra = s_dist_extra[dist];
2657                 dist = s_dist_base[dist];
2658                 if (num_extra)
2659                 {
2660                     mz_uint extra_bits;
2661                     TINFL_GET_BITS(27, extra_bits, num_extra);
2662                     dist += extra_bits;
2663                 }
2664 
2665                 dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2666                 if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2667                 {
2668                     TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2669                 }
2670 
2671                 pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2672 
2673                 if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2674                 {
2675                     while (counter--)
2676                     {
2677                         while (pOut_buf_cur >= pOut_buf_end)
2678                         {
2679                             TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2680                         }
2681                         *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2682                     }
2683                     continue;
2684                 }
2685 #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2686                 else if ((counter >= 9) && (counter <= dist))
2687                 {
2688                     const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2689                     do
2690                     {
2691                         ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2692                         ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2693                         pOut_buf_cur += 8;
2694                     } while ((pSrc += 8) < pSrc_end);
2695                     if ((counter &= 7) < 3)
2696                     {
2697                         if (counter)
2698                         {
2699                             pOut_buf_cur[0] = pSrc[0];
2700                             if (counter > 1)
2701                                 pOut_buf_cur[1] = pSrc[1];
2702                             pOut_buf_cur += counter;
2703                         }
2704                         continue;
2705                     }
2706                 }
2707 #endif
2708                 do
2709                 {
2710                     pOut_buf_cur[0] = pSrc[0];
2711                     pOut_buf_cur[1] = pSrc[1];
2712                     pOut_buf_cur[2] = pSrc[2];
2713                     pOut_buf_cur += 3;
2714                     pSrc += 3;
2715                 } while ((int)(counter -= 3) > 2);
2716                 if ((int)counter > 0)
2717                 {
2718                     pOut_buf_cur[0] = pSrc[0];
2719                     if ((int)counter > 1)
2720                         pOut_buf_cur[1] = pSrc[1];
2721                     pOut_buf_cur += counter;
2722                 }
2723             }
2724         }
2725     } while (!(r->m_final & 1));
2726 
2727     /* 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. */
2728     /* 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. */
2729     TINFL_SKIP_BITS(32, num_bits & 7);
2730     while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2731     {
2732         --pIn_buf_cur;
2733         num_bits -= 8;
2734     }
2735     bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2736     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). */
2737 
2738     if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2739     {
2740         for (counter = 0; counter < 4; ++counter)
2741         {
2742             mz_uint s;
2743             if (num_bits)
2744                 TINFL_GET_BITS(41, s, 8);
2745             else
2746                 TINFL_GET_BYTE(42, s);
2747             r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2748         }
2749     }
2750     TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2751 
2752     TINFL_CR_FINISH
2753 
2754 common_exit:
2755     /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
2756     /* 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. */
2757     /* 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. */
2758     if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
2759     {
2760         while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2761         {
2762             --pIn_buf_cur;
2763             num_bits -= 8;
2764         }
2765     }
2766     r->m_num_bits = num_bits;
2767     r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2768     r->m_dist = dist;
2769     r->m_counter = counter;
2770     r->m_num_extra = num_extra;
2771     r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2772     *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2773     *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2774     if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2775     {
2776         const mz_uint8 *ptr = pOut_buf_next;
2777         size_t buf_len = *pOut_buf_size;
2778         mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2779         size_t block_len = buf_len % 5552;
2780         while (buf_len)
2781         {
2782             for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2783             {
2784                 s1 += ptr[0], s2 += s1;
2785                 s1 += ptr[1], s2 += s1;
2786                 s1 += ptr[2], s2 += s1;
2787                 s1 += ptr[3], s2 += s1;
2788                 s1 += ptr[4], s2 += s1;
2789                 s1 += ptr[5], s2 += s1;
2790                 s1 += ptr[6], s2 += s1;
2791                 s1 += ptr[7], s2 += s1;
2792             }
2793             for (; i < block_len; ++i)
2794                 s1 += *ptr++, s2 += s1;
2795             s1 %= 65521U, s2 %= 65521U;
2796             buf_len -= block_len;
2797             block_len = 5552;
2798         }
2799         r->m_check_adler32 = (s2 << 16) + s1;
2800         if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2801             status = TINFL_STATUS_ADLER32_MISMATCH;
2802     }
2803     return status;
2804 }
2805 
2806 /* Higher level helper functions. */
tinfl_decompress_mem_to_heap(const void * pSrc_buf,size_t src_buf_len,size_t * pOut_len,int flags)2807 void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2808 {
2809     tinfl_decompressor decomp;
2810     void *pBuf = NULL, *pNew_buf;
2811     size_t src_buf_ofs = 0, out_buf_capacity = 0;
2812     *pOut_len = 0;
2813     tinfl_init(&decomp);
2814     for (;;)
2815     {
2816         size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2817         tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8 *)pBuf, pBuf ? (mz_uint8 *)pBuf + *pOut_len : NULL, &dst_buf_size,
2818                                                (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2819         if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2820         {
2821             MZ_FREE(pBuf);
2822             *pOut_len = 0;
2823             return NULL;
2824         }
2825         src_buf_ofs += src_buf_size;
2826         *pOut_len += dst_buf_size;
2827         if (status == TINFL_STATUS_DONE)
2828             break;
2829         new_out_buf_capacity = out_buf_capacity * 2;
2830         if (new_out_buf_capacity < 128)
2831             new_out_buf_capacity = 128;
2832         pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2833         if (!pNew_buf)
2834         {
2835             MZ_FREE(pBuf);
2836             *pOut_len = 0;
2837             return NULL;
2838         }
2839         pBuf = pNew_buf;
2840         out_buf_capacity = new_out_buf_capacity;
2841     }
2842     return pBuf;
2843 }
2844 
tinfl_decompress_mem_to_mem(void * pOut_buf,size_t out_buf_len,const void * pSrc_buf,size_t src_buf_len,int flags)2845 size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags)
2846 {
2847     tinfl_decompressor decomp;
2848     tinfl_status status;
2849     tinfl_init(&decomp);
2850     status = tinfl_decompress(&decomp, (const mz_uint8 *)pSrc_buf, &src_buf_len, (mz_uint8 *)pOut_buf, (mz_uint8 *)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2851     return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2852 }
2853 
tinfl_decompress_mem_to_callback(const void * pIn_buf,size_t * pIn_buf_size,tinfl_put_buf_func_ptr pPut_buf_func,void * pPut_buf_user,int flags)2854 int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
2855 {
2856     int result = 0;
2857     tinfl_decompressor decomp;
2858     mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2859     size_t in_buf_ofs = 0, dict_ofs = 0;
2860     if (!pDict)
2861         return TINFL_STATUS_FAILED;
2862     tinfl_init(&decomp);
2863     for (;;)
2864     {
2865         size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2866         tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2867                                                (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2868         in_buf_ofs += in_buf_size;
2869         if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2870             break;
2871         if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2872         {
2873             result = (status == TINFL_STATUS_DONE);
2874             break;
2875         }
2876         dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
2877     }
2878     MZ_FREE(pDict);
2879     *pIn_buf_size = in_buf_ofs;
2880     return result;
2881 }
2882 
tinfl_decompressor_alloc()2883 tinfl_decompressor *tinfl_decompressor_alloc()
2884 {
2885     tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));
2886     if (pDecomp)
2887         tinfl_init(pDecomp);
2888     return pDecomp;
2889 }
2890 
tinfl_decompressor_free(tinfl_decompressor * pDecomp)2891 void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
2892 {
2893     MZ_FREE(pDecomp);
2894 }
2895 
2896 #ifdef __cplusplus
2897 }
2898 #endif
2899 /**************************************************************************
2900  *
2901  * Copyright 2013-2014 RAD Game Tools and Valve Software
2902  * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2903  * Copyright 2016 Martin Raiber
2904  * All Rights Reserved.
2905  *
2906  * Permission is hereby granted, free of charge, to any person obtaining a copy
2907  * of this software and associated documentation files (the "Software"), to deal
2908  * in the Software without restriction, including without limitation the rights
2909  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2910  * copies of the Software, and to permit persons to whom the Software is
2911  * furnished to do so, subject to the following conditions:
2912  *
2913  * The above copyright notice and this permission notice shall be included in
2914  * all copies or substantial portions of the Software.
2915  *
2916  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2917  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2918  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2919  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2920  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2921  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2922  * THE SOFTWARE.
2923  *
2924  **************************************************************************/
2925 
2926 
2927 #ifndef MINIZ_NO_ARCHIVE_APIS
2928 
2929 #ifdef __cplusplus
2930 extern "C" {
2931 #endif
2932 
2933 /* ------------------- .ZIP archive reading */
2934 
2935 #ifdef MINIZ_NO_STDIO
2936 #define MZ_FILE void *
2937 #else
2938 #include <sys/stat.h>
2939 
2940 #if defined(_MSC_VER) || defined(__MINGW64__)
2941 static FILE *mz_fopen(const char *pFilename, const char *pMode)
2942 {
2943     FILE *pFile = NULL;
2944     fopen_s(&pFile, pFilename, pMode);
2945     return pFile;
2946 }
2947 static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
2948 {
2949     FILE *pFile = NULL;
2950     if (freopen_s(&pFile, pPath, pMode, pStream))
2951         return NULL;
2952     return pFile;
2953 }
2954 #ifndef MINIZ_NO_TIME
2955 #include <sys/utime.h>
2956 #endif
2957 #define MZ_FOPEN mz_fopen
2958 #define MZ_FCLOSE fclose
2959 #define MZ_FREAD fread
2960 #define MZ_FWRITE fwrite
2961 #define MZ_FTELL64 _ftelli64
2962 #define MZ_FSEEK64 _fseeki64
2963 #define MZ_FILE_STAT_STRUCT _stat
2964 #define MZ_FILE_STAT _stat
2965 #define MZ_FFLUSH fflush
2966 #define MZ_FREOPEN mz_freopen
2967 #define MZ_DELETE_FILE remove
2968 #elif defined(__MINGW32__)
2969 #ifndef MINIZ_NO_TIME
2970 #include <sys/utime.h>
2971 #endif
2972 #define MZ_FOPEN(f, m) fopen(f, m)
2973 #define MZ_FCLOSE fclose
2974 #define MZ_FREAD fread
2975 #define MZ_FWRITE fwrite
2976 #define MZ_FTELL64 ftello64
2977 #define MZ_FSEEK64 fseeko64
2978 #define MZ_FILE_STAT_STRUCT _stat
2979 #define MZ_FILE_STAT _stat
2980 #define MZ_FFLUSH fflush
2981 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2982 #define MZ_DELETE_FILE remove
2983 #elif defined(__TINYC__)
2984 #ifndef MINIZ_NO_TIME
2985 #include <sys/utime.h>
2986 #endif
2987 #define MZ_FOPEN(f, m) fopen(f, m)
2988 #define MZ_FCLOSE fclose
2989 #define MZ_FREAD fread
2990 #define MZ_FWRITE fwrite
2991 #define MZ_FTELL64 ftell
2992 #define MZ_FSEEK64 fseek
2993 #define MZ_FILE_STAT_STRUCT stat
2994 #define MZ_FILE_STAT stat
2995 #define MZ_FFLUSH fflush
2996 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
2997 #define MZ_DELETE_FILE remove
2998 #elif defined(__GNUC__) && _LARGEFILE64_SOURCE
2999 #ifndef MINIZ_NO_TIME
3000 #include <utime.h>
3001 #endif
3002 #define MZ_FOPEN(f, m) fopen64(f, m)
3003 #define MZ_FCLOSE fclose
3004 #define MZ_FREAD fread
3005 #define MZ_FWRITE fwrite
3006 #define MZ_FTELL64 ftello64
3007 #define MZ_FSEEK64 fseeko64
3008 #define MZ_FILE_STAT_STRUCT stat64
3009 #define MZ_FILE_STAT stat64
3010 #define MZ_FFLUSH fflush
3011 #define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
3012 #define MZ_DELETE_FILE remove
3013 #elif defined(__APPLE__) && _LARGEFILE64_SOURCE
3014 #ifndef MINIZ_NO_TIME
3015 #include <utime.h>
3016 #endif
3017 #define MZ_FOPEN(f, m) fopen(f, m)
3018 #define MZ_FCLOSE fclose
3019 #define MZ_FREAD fread
3020 #define MZ_FWRITE fwrite
3021 #define MZ_FTELL64 ftello
3022 #define MZ_FSEEK64 fseeko
3023 #define MZ_FILE_STAT_STRUCT stat
3024 #define MZ_FILE_STAT stat
3025 #define MZ_FFLUSH fflush
3026 #define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3027 #define MZ_DELETE_FILE remove
3028 
3029 #else
3030 #pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3031 #ifndef MINIZ_NO_TIME
3032 #include <utime.h>
3033 #endif
3034 #define MZ_FOPEN(f, m) fopen(f, m)
3035 #define MZ_FCLOSE fclose
3036 #define MZ_FREAD fread
3037 #define MZ_FWRITE fwrite
3038 #ifdef __STRICT_ANSI__
3039 #define MZ_FTELL64 ftell
3040 #define MZ_FSEEK64 fseek
3041 #else
3042 #define MZ_FTELL64 ftello
3043 #define MZ_FSEEK64 fseeko
3044 #endif
3045 #define MZ_FILE_STAT_STRUCT stat
3046 #define MZ_FILE_STAT stat
3047 #define MZ_FFLUSH fflush
3048 #define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3049 #define MZ_DELETE_FILE remove
3050 #endif /* #ifdef _MSC_VER */
3051 #endif /* #ifdef MINIZ_NO_STDIO */
3052 
3053 #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3054 
3055 /* 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. */
3056 enum
3057 {
3058     /* ZIP archive identifiers and record sizes */
3059     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
3060     MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
3061     MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
3062     MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
3063     MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
3064     MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
3065 
3066     /* ZIP64 archive identifier and record sizes */
3067     MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
3068     MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
3069     MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
3070     MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
3071     MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
3072     MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
3073     MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
3074     MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
3075 
3076     /* Central directory header record offsets */
3077     MZ_ZIP_CDH_SIG_OFS = 0,
3078     MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
3079     MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
3080     MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
3081     MZ_ZIP_CDH_METHOD_OFS = 10,
3082     MZ_ZIP_CDH_FILE_TIME_OFS = 12,
3083     MZ_ZIP_CDH_FILE_DATE_OFS = 14,
3084     MZ_ZIP_CDH_CRC32_OFS = 16,
3085     MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
3086     MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
3087     MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
3088     MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
3089     MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
3090     MZ_ZIP_CDH_DISK_START_OFS = 34,
3091     MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
3092     MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
3093     MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
3094 
3095     /* Local directory header offsets */
3096     MZ_ZIP_LDH_SIG_OFS = 0,
3097     MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
3098     MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
3099     MZ_ZIP_LDH_METHOD_OFS = 8,
3100     MZ_ZIP_LDH_FILE_TIME_OFS = 10,
3101     MZ_ZIP_LDH_FILE_DATE_OFS = 12,
3102     MZ_ZIP_LDH_CRC32_OFS = 14,
3103     MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
3104     MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
3105     MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
3106     MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
3107     MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
3108 
3109     /* End of central directory offsets */
3110     MZ_ZIP_ECDH_SIG_OFS = 0,
3111     MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
3112     MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
3113     MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
3114     MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
3115     MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
3116     MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
3117     MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
3118 
3119     /* ZIP64 End of central directory locator offsets */
3120     MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */
3121     MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */
3122     MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */
3123     MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
3124 
3125     /* ZIP64 End of central directory header offsets */
3126     MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */
3127     MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */
3128     MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */
3129     MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */
3130     MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */
3131     MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */
3132     MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
3133     MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */
3134     MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */
3135     MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */
3136     MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
3137     MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
3138     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
3139     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
3140     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
3141     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
3142     MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
3143 };
3144 
3145 typedef struct
3146 {
3147     void *m_p;
3148     size_t m_size, m_capacity;
3149     mz_uint m_element_size;
3150 } mz_zip_array;
3151 
3152 struct mz_zip_internal_state_tag
3153 {
3154     mz_zip_array m_central_dir;
3155     mz_zip_array m_central_dir_offsets;
3156     mz_zip_array m_sorted_central_dir_offsets;
3157 
3158     /* The flags passed in when the archive is initially opened. */
3159     uint32_t m_init_flags;
3160 
3161     /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
3162     mz_bool m_zip64;
3163 
3164     /* 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.) */
3165     mz_bool m_zip64_has_extended_info_fields;
3166 
3167     /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
3168     MZ_FILE *m_pFile;
3169     mz_uint64 m_file_archive_start_ofs;
3170 
3171     void *m_pMem;
3172     size_t m_mem_size;
3173     size_t m_mem_capacity;
3174 };
3175 
3176 #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3177 
3178 #if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)
mz_zip_array_range_check(const mz_zip_array * pArray,mz_uint index)3179 static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
3180 {
3181     MZ_ASSERT(index < pArray->m_size);
3182     return index;
3183 }
3184 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3185 #else
3186 #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3187 #endif
3188 
mz_zip_array_init(mz_zip_array * pArray,mz_uint32 element_size)3189 static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
3190 {
3191     memset(pArray, 0, sizeof(mz_zip_array));
3192     pArray->m_element_size = element_size;
3193 }
3194 
mz_zip_array_clear(mz_zip_archive * pZip,mz_zip_array * pArray)3195 static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
3196 {
3197     pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3198     memset(pArray, 0, sizeof(mz_zip_array));
3199 }
3200 
mz_zip_array_ensure_capacity(mz_zip_archive * pZip,mz_zip_array * pArray,size_t min_new_capacity,mz_uint growing)3201 static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
3202 {
3203     void *pNew_p;
3204     size_t new_capacity = min_new_capacity;
3205     MZ_ASSERT(pArray->m_element_size);
3206     if (pArray->m_capacity >= min_new_capacity)
3207         return MZ_TRUE;
3208     if (growing)
3209     {
3210         new_capacity = MZ_MAX(1, pArray->m_capacity);
3211         while (new_capacity < min_new_capacity)
3212             new_capacity *= 2;
3213     }
3214     if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3215         return MZ_FALSE;
3216     pArray->m_p = pNew_p;
3217     pArray->m_capacity = new_capacity;
3218     return MZ_TRUE;
3219 }
3220 
mz_zip_array_reserve(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_capacity,mz_uint growing)3221 static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3222 {
3223     if (new_capacity > pArray->m_capacity)
3224     {
3225         if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3226             return MZ_FALSE;
3227     }
3228     return MZ_TRUE;
3229 }
3230 
mz_zip_array_resize(mz_zip_archive * pZip,mz_zip_array * pArray,size_t new_size,mz_uint growing)3231 static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3232 {
3233     if (new_size > pArray->m_capacity)
3234     {
3235         if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3236             return MZ_FALSE;
3237     }
3238     pArray->m_size = new_size;
3239     return MZ_TRUE;
3240 }
3241 
mz_zip_array_ensure_room(mz_zip_archive * pZip,mz_zip_array * pArray,size_t n)3242 static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3243 {
3244     return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3245 }
3246 
mz_zip_array_push_back(mz_zip_archive * pZip,mz_zip_array * pArray,const void * pElements,size_t n)3247 static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3248 {
3249     size_t orig_size = pArray->m_size;
3250     if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3251         return MZ_FALSE;
3252     memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3253     return MZ_TRUE;
3254 }
3255 
3256 #ifndef MINIZ_NO_TIME
mz_zip_dos_to_time_t(int dos_time,int dos_date)3257 static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3258 {
3259     struct tm tm;
3260     memset(&tm, 0, sizeof(tm));
3261     tm.tm_isdst = -1;
3262     tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3263     tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3264     tm.tm_mday = dos_date & 31;
3265     tm.tm_hour = (dos_time >> 11) & 31;
3266     tm.tm_min = (dos_time >> 5) & 63;
3267     tm.tm_sec = (dos_time << 1) & 62;
3268     return mktime(&tm);
3269 }
3270 
3271 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_time_t_to_dos_time(MZ_TIME_T time,mz_uint16 * pDOS_time,mz_uint16 * pDOS_date)3272 static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3273 {
3274 #ifdef _MSC_VER
3275     struct tm tm_struct;
3276     struct tm *tm = &tm_struct;
3277     errno_t err = localtime_s(tm, &time);
3278     if (err)
3279     {
3280         *pDOS_date = 0;
3281         *pDOS_time = 0;
3282         return;
3283     }
3284 #else
3285     struct tm *tm = localtime(&time);
3286 #endif /* #ifdef _MSC_VER */
3287 
3288     *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3289     *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3290 }
3291 #endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
3292 
3293 #ifndef MINIZ_NO_STDIO
3294 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
mz_zip_get_file_modified_time(const char * pFilename,MZ_TIME_T * pTime)3295 static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
3296 {
3297     struct MZ_FILE_STAT_STRUCT file_stat;
3298 
3299     /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
3300     if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3301         return MZ_FALSE;
3302 
3303     *pTime = file_stat.st_mtime;
3304 
3305     return MZ_TRUE;
3306 }
3307 #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
3308 
mz_zip_set_file_times(const char * pFilename,MZ_TIME_T access_time,MZ_TIME_T modified_time)3309 static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3310 {
3311     struct utimbuf t;
3312 
3313     memset(&t, 0, sizeof(t));
3314     t.actime = access_time;
3315     t.modtime = modified_time;
3316 
3317     return !utime(pFilename, &t);
3318 }
3319 #endif /* #ifndef MINIZ_NO_STDIO */
3320 #endif /* #ifndef MINIZ_NO_TIME */
3321 
mz_zip_set_error(mz_zip_archive * pZip,mz_zip_error err_num)3322 static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
3323 {
3324     if (pZip)
3325         pZip->m_last_error = err_num;
3326     return MZ_FALSE;
3327 }
3328 
mz_zip_reader_init_internal(mz_zip_archive * pZip,mz_uint flags)3329 static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
3330 {
3331     (void)flags;
3332     if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3333         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3334 
3335     if (!pZip->m_pAlloc)
3336         pZip->m_pAlloc = miniz_def_alloc_func;
3337     if (!pZip->m_pFree)
3338         pZip->m_pFree = miniz_def_free_func;
3339     if (!pZip->m_pRealloc)
3340         pZip->m_pRealloc = miniz_def_realloc_func;
3341 
3342     pZip->m_archive_size = 0;
3343     pZip->m_central_directory_file_ofs = 0;
3344     pZip->m_total_files = 0;
3345     pZip->m_last_error = MZ_ZIP_NO_ERROR;
3346 
3347     if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3348         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3349 
3350     memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3351     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3352     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3353     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3354     pZip->m_pState->m_init_flags = flags;
3355     pZip->m_pState->m_zip64 = MZ_FALSE;
3356     pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
3357 
3358     pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3359 
3360     return MZ_TRUE;
3361 }
3362 
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)3363 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)
3364 {
3365     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;
3366     const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3367     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);
3368     mz_uint8 l = 0, r = 0;
3369     pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3370     pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3371     pE = pL + MZ_MIN(l_len, r_len);
3372     while (pL < pE)
3373     {
3374         if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3375             break;
3376         pL++;
3377         pR++;
3378     }
3379     return (pL == pE) ? (l_len < r_len) : (l < r);
3380 }
3381 
3382 #define MZ_SWAP_UINT32(a, b) \
3383     do                       \
3384     {                        \
3385         mz_uint32 t = a;     \
3386         a = b;               \
3387         b = t;               \
3388     }                        \
3389     MZ_MACRO_END
3390 
3391 /* 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)3392 static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
3393 {
3394     mz_zip_internal_state *pState = pZip->m_pState;
3395     const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3396     const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3397     mz_uint32 *pIndices;
3398     mz_uint32 start, end;
3399     const mz_uint32 size = pZip->m_total_files;
3400 
3401     if (size <= 1U)
3402         return;
3403 
3404     pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3405 
3406     start = (size - 2U) >> 1U;
3407     for (;;)
3408     {
3409         mz_uint64 child, root = start;
3410         for (;;)
3411         {
3412             if ((child = (root << 1U) + 1U) >= size)
3413                 break;
3414             child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3415             if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3416                 break;
3417             MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3418             root = child;
3419         }
3420         if (!start)
3421             break;
3422         start--;
3423     }
3424 
3425     end = size - 1;
3426     while (end > 0)
3427     {
3428         mz_uint64 child, root = 0;
3429         MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3430         for (;;)
3431         {
3432             if ((child = (root << 1U) + 1U) >= end)
3433                 break;
3434             child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3435             if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3436                 break;
3437             MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3438             root = child;
3439         }
3440         end--;
3441     }
3442 }
3443 
mz_zip_reader_locate_header_sig(mz_zip_archive * pZip,mz_uint32 record_sig,mz_uint32 record_size,mz_int64 * pOfs)3444 static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
3445 {
3446     mz_int64 cur_file_ofs;
3447     mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3448     mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3449 
3450     /* Basic sanity checks - reject files which are too small */
3451     if (pZip->m_archive_size < record_size)
3452         return MZ_FALSE;
3453 
3454     /* Find the record by scanning the file from the end towards the beginning. */
3455     cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3456     for (;;)
3457     {
3458         int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3459 
3460         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3461             return MZ_FALSE;
3462 
3463         for (i = n - 4; i >= 0; --i)
3464         {
3465             mz_uint s = MZ_READ_LE32(pBuf + i);
3466             if (s == record_sig)
3467             {
3468                 if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3469                     break;
3470             }
3471         }
3472 
3473         if (i >= 0)
3474         {
3475             cur_file_ofs += i;
3476             break;
3477         }
3478 
3479         /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3480         if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
3481             return MZ_FALSE;
3482 
3483         cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3484     }
3485 
3486     *pOfs = cur_file_ofs;
3487     return MZ_TRUE;
3488 }
3489 
mz_zip_reader_read_central_dir(mz_zip_archive * pZip,mz_uint flags)3490 static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
3491 {
3492     mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3493     mz_uint64 cdir_ofs = 0;
3494     mz_int64 cur_file_ofs = 0;
3495     const mz_uint8 *p;
3496 
3497     mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3498     mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3499     mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3500     mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3501     mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3502 
3503     mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3504     mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3505 
3506     mz_uint64 zip64_end_of_central_dir_ofs = 0;
3507 
3508     /* 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. */
3509     if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3510         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3511 
3512     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))
3513         return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
3514 
3515     /* Read and verify the end of central directory record. */
3516     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)
3517         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3518 
3519     if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3520         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3521 
3522     if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3523     {
3524         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)
3525         {
3526             if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
3527             {
3528                 zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3529                 if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3530                     return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3531 
3532                 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)
3533                 {
3534                     if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
3535                     {
3536                         pZip->m_pState->m_zip64 = MZ_TRUE;
3537                     }
3538                 }
3539             }
3540         }
3541     }
3542 
3543     pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3544     cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3545     num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3546     cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3547     cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3548     cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3549 
3550     if (pZip->m_pState->m_zip64)
3551     {
3552         mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3553         mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3554         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);
3555         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);
3556         mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3557 
3558         if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3559             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3560 
3561         if (zip64_total_num_of_disks != 1U)
3562             return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3563 
3564         /* Check for miniz's practical limits */
3565         if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3566             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3567 
3568         pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3569 
3570         if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3571             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3572 
3573         cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3574 
3575         /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
3576         if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3577             return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
3578 
3579         cdir_size = (mz_uint32)zip64_size_of_central_directory;
3580 
3581         num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3582 
3583         cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3584 
3585         cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3586     }
3587 
3588     if (pZip->m_total_files != cdir_entries_on_this_disk)
3589         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3590 
3591     if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3592         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3593 
3594     if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3595         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3596 
3597     if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3598         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3599 
3600     pZip->m_central_directory_file_ofs = cdir_ofs;
3601 
3602     if (pZip->m_total_files)
3603     {
3604         mz_uint i, n;
3605         /* 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. */
3606         if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3607             (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3608             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3609 
3610         if (sort_central_dir)
3611         {
3612             if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3613                 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3614         }
3615 
3616         if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3617             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3618 
3619         /* Now create an index into the central directory file records, do some basic sanity checking on each record */
3620         p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3621         for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3622         {
3623             mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3624             mz_uint64 comp_size, decomp_size, local_header_ofs;
3625 
3626             if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3627                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3628 
3629             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);
3630 
3631             if (sort_central_dir)
3632                 MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3633 
3634             comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3635             decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3636             local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3637             filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3638             ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3639 
3640             if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
3641                 (ext_data_size) &&
3642                 (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3643             {
3644                 /* Attempt to find zip64 extended information field in the entry's extra data */
3645                 mz_uint32 extra_size_remaining = ext_data_size;
3646 
3647                 if (extra_size_remaining)
3648                 {
3649                     const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3650 
3651                     do
3652                     {
3653                         mz_uint32 field_id;
3654                         mz_uint32 field_data_size;
3655 
3656                         if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3657                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3658 
3659                         field_id = MZ_READ_LE16(pExtra_data);
3660                         field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3661 
3662                         if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3663                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3664 
3665                         if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
3666                         {
3667                             /* 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). */
3668                             pZip->m_pState->m_zip64 = MZ_TRUE;
3669                             pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
3670                             break;
3671                         }
3672 
3673                         pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3674                         extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3675                     } while (extra_size_remaining);
3676                 }
3677             }
3678 
3679             /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3680             if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3681             {
3682                 if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3683                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3684             }
3685 
3686             disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3687             if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3688                 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3689 
3690             if (comp_size != MZ_UINT32_MAX)
3691             {
3692                 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)
3693                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3694             }
3695 
3696             bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3697             if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
3698                 return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3699 
3700             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)
3701                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3702 
3703             n -= total_header_size;
3704             p += total_header_size;
3705         }
3706     }
3707 
3708     if (sort_central_dir)
3709         mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3710 
3711     return MZ_TRUE;
3712 }
3713 
mz_zip_zero_struct(mz_zip_archive * pZip)3714 void mz_zip_zero_struct(mz_zip_archive *pZip)
3715 {
3716     if (pZip)
3717         MZ_CLEAR_OBJ(*pZip);
3718 }
3719 
mz_zip_reader_end_internal(mz_zip_archive * pZip,mz_bool set_last_error)3720 static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
3721 {
3722     mz_bool status = MZ_TRUE;
3723 
3724     if (!pZip)
3725         return MZ_FALSE;
3726 
3727     if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3728     {
3729         if (set_last_error)
3730             pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
3731 
3732         return MZ_FALSE;
3733     }
3734 
3735     if (pZip->m_pState)
3736     {
3737         mz_zip_internal_state *pState = pZip->m_pState;
3738         pZip->m_pState = NULL;
3739 
3740         mz_zip_array_clear(pZip, &pState->m_central_dir);
3741         mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3742         mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3743 
3744 #ifndef MINIZ_NO_STDIO
3745         if (pState->m_pFile)
3746         {
3747             if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3748             {
3749                 if (MZ_FCLOSE(pState->m_pFile) == EOF)
3750                 {
3751                     if (set_last_error)
3752                         pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
3753                     status = MZ_FALSE;
3754                 }
3755             }
3756             pState->m_pFile = NULL;
3757         }
3758 #endif /* #ifndef MINIZ_NO_STDIO */
3759 
3760         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3761     }
3762     pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3763 
3764     return status;
3765 }
3766 
mz_zip_reader_end(mz_zip_archive * pZip)3767 mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3768 {
3769     return mz_zip_reader_end_internal(pZip, MZ_TRUE);
3770 }
mz_zip_reader_init(mz_zip_archive * pZip,mz_uint64 size,mz_uint flags)3771 mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
3772 {
3773     if ((!pZip) || (!pZip->m_pRead))
3774         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3775 
3776     if (!mz_zip_reader_init_internal(pZip, flags))
3777         return MZ_FALSE;
3778 
3779     pZip->m_zip_type = MZ_ZIP_TYPE_USER;
3780     pZip->m_archive_size = size;
3781 
3782     if (!mz_zip_reader_read_central_dir(pZip, flags))
3783     {
3784         mz_zip_reader_end_internal(pZip, MZ_FALSE);
3785         return MZ_FALSE;
3786     }
3787 
3788     return MZ_TRUE;
3789 }
3790 
mz_zip_mem_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)3791 static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3792 {
3793     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3794     size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3795     memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3796     return s;
3797 }
3798 
mz_zip_reader_init_mem(mz_zip_archive * pZip,const void * pMem,size_t size,mz_uint flags)3799 mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
3800 {
3801     if (!pMem)
3802         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3803 
3804     if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3805         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3806 
3807     if (!mz_zip_reader_init_internal(pZip, flags))
3808         return MZ_FALSE;
3809 
3810     pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
3811     pZip->m_archive_size = size;
3812     pZip->m_pRead = mz_zip_mem_read_func;
3813     pZip->m_pIO_opaque = pZip;
3814     pZip->m_pNeeds_keepalive = NULL;
3815 
3816 #ifdef __cplusplus
3817     pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3818 #else
3819     pZip->m_pState->m_pMem = (void *)pMem;
3820 #endif
3821 
3822     pZip->m_pState->m_mem_size = size;
3823 
3824     if (!mz_zip_reader_read_central_dir(pZip, flags))
3825     {
3826         mz_zip_reader_end_internal(pZip, MZ_FALSE);
3827         return MZ_FALSE;
3828     }
3829 
3830     return MZ_TRUE;
3831 }
3832 
3833 #ifndef MINIZ_NO_STDIO
mz_zip_file_read_func(void * pOpaque,mz_uint64 file_ofs,void * pBuf,size_t n)3834 static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3835 {
3836     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3837     mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
3838 
3839     file_ofs += pZip->m_pState->m_file_archive_start_ofs;
3840 
3841     if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
3842         return 0;
3843 
3844     return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
3845 }
3846 
mz_zip_reader_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint32 flags)3847 mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
3848 {
3849     return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
3850 }
3851 
mz_zip_reader_init_file_v2(mz_zip_archive * pZip,const char * pFilename,mz_uint flags,mz_uint64 file_start_ofs,mz_uint64 archive_size)3852 mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size)
3853 {
3854     mz_uint64 file_size;
3855     MZ_FILE *pFile;
3856 
3857     if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
3858         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3859 
3860     pFile = MZ_FOPEN(pFilename, "rb");
3861     if (!pFile)
3862         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
3863 
3864     file_size = archive_size;
3865     if (!file_size)
3866     {
3867         if (MZ_FSEEK64(pFile, 0, SEEK_END))
3868         {
3869             MZ_FCLOSE(pFile);
3870             return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
3871         }
3872 
3873         file_size = MZ_FTELL64(pFile);
3874     }
3875 
3876     /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
3877 
3878     if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3879     {
3880 	MZ_FCLOSE(pFile);
3881         return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3882     }
3883 
3884     if (!mz_zip_reader_init_internal(pZip, flags))
3885     {
3886         MZ_FCLOSE(pFile);
3887         return MZ_FALSE;
3888     }
3889 
3890     pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
3891     pZip->m_pRead = mz_zip_file_read_func;
3892     pZip->m_pIO_opaque = pZip;
3893     pZip->m_pState->m_pFile = pFile;
3894     pZip->m_archive_size = file_size;
3895     pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
3896 
3897     if (!mz_zip_reader_read_central_dir(pZip, flags))
3898     {
3899         mz_zip_reader_end_internal(pZip, MZ_FALSE);
3900         return MZ_FALSE;
3901     }
3902 
3903     return MZ_TRUE;
3904 }
3905 
mz_zip_reader_init_cfile(mz_zip_archive * pZip,MZ_FILE * pFile,mz_uint64 archive_size,mz_uint flags)3906 mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
3907 {
3908     mz_uint64 cur_file_ofs;
3909 
3910     if ((!pZip) || (!pFile))
3911         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
3912 
3913     cur_file_ofs = MZ_FTELL64(pFile);
3914 
3915     if (!archive_size)
3916     {
3917         if (MZ_FSEEK64(pFile, 0, SEEK_END))
3918             return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
3919 
3920         archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
3921 
3922         if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3923             return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3924     }
3925 
3926     if (!mz_zip_reader_init_internal(pZip, flags))
3927         return MZ_FALSE;
3928 
3929     pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
3930     pZip->m_pRead = mz_zip_file_read_func;
3931 
3932     pZip->m_pIO_opaque = pZip;
3933     pZip->m_pState->m_pFile = pFile;
3934     pZip->m_archive_size = archive_size;
3935     pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
3936 
3937     if (!mz_zip_reader_read_central_dir(pZip, flags))
3938     {
3939         mz_zip_reader_end_internal(pZip, MZ_FALSE);
3940         return MZ_FALSE;
3941     }
3942 
3943     return MZ_TRUE;
3944 }
3945 
3946 #endif /* #ifndef MINIZ_NO_STDIO */
3947 
mz_zip_get_cdh(mz_zip_archive * pZip,mz_uint file_index)3948 static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
3949 {
3950     if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
3951         return NULL;
3952     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));
3953 }
3954 
mz_zip_reader_is_file_encrypted(mz_zip_archive * pZip,mz_uint file_index)3955 mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
3956 {
3957     mz_uint m_bit_flag;
3958     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
3959     if (!p)
3960     {
3961         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3962         return MZ_FALSE;
3963     }
3964 
3965     m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3966     return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
3967 }
3968 
mz_zip_reader_is_file_supported(mz_zip_archive * pZip,mz_uint file_index)3969 mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
3970 {
3971     mz_uint bit_flag;
3972     mz_uint method;
3973 
3974     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
3975     if (!p)
3976     {
3977         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3978         return MZ_FALSE;
3979     }
3980 
3981     method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
3982     bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3983 
3984     if ((method != 0) && (method != MZ_DEFLATED))
3985     {
3986         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
3987         return MZ_FALSE;
3988     }
3989 
3990     if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
3991     {
3992         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3993         return MZ_FALSE;
3994     }
3995 
3996     if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
3997     {
3998         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
3999         return MZ_FALSE;
4000     }
4001 
4002     return MZ_TRUE;
4003 }
4004 
mz_zip_reader_is_file_a_directory(mz_zip_archive * pZip,mz_uint file_index)4005 mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
4006 {
4007     mz_uint filename_len, attribute_mapping_id, external_attr;
4008     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4009     if (!p)
4010     {
4011         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4012         return MZ_FALSE;
4013     }
4014 
4015     filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4016     if (filename_len)
4017     {
4018         if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4019             return MZ_TRUE;
4020     }
4021 
4022     /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
4023     /* 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. */
4024     /* FIXME: Remove this check? Is it necessary - we already check the filename. */
4025     attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4026     (void)attribute_mapping_id;
4027 
4028     external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4029     if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4030     {
4031         return MZ_TRUE;
4032     }
4033 
4034     return MZ_FALSE;
4035 }
4036 
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)4037 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)
4038 {
4039     mz_uint n;
4040     const mz_uint8 *p = pCentral_dir_header;
4041 
4042     if (pFound_zip64_extra_data)
4043         *pFound_zip64_extra_data = MZ_FALSE;
4044 
4045     if ((!p) || (!pStat))
4046         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4047 
4048     /* Extract fields from the central directory record. */
4049     pStat->m_file_index = file_index;
4050     pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
4051     pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
4052     pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
4053     pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4054     pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4055 #ifndef MINIZ_NO_TIME
4056     pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS));
4057 #endif
4058     pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
4059     pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4060     pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4061     pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
4062     pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4063     pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4064 
4065     /* Copy as much of the filename and comment as possible. */
4066     n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4067     n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
4068     memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4069     pStat->m_filename[n] = '\0';
4070 
4071     n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4072     n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
4073     pStat->m_comment_size = n;
4074     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);
4075     pStat->m_comment[n] = '\0';
4076 
4077     /* Set some flags for convienance */
4078     pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4079     pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4080     pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4081 
4082     /* See if we need to read any zip64 extended information fields. */
4083     /* 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). */
4084     if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
4085     {
4086         /* Attempt to find zip64 extended information field in the entry's extra data */
4087         mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4088 
4089         if (extra_size_remaining)
4090         {
4091             const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4092 
4093             do
4094             {
4095                 mz_uint32 field_id;
4096                 mz_uint32 field_data_size;
4097 
4098                 if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4099                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4100 
4101                 field_id = MZ_READ_LE16(pExtra_data);
4102                 field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4103 
4104                 if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4105                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4106 
4107                 if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
4108                 {
4109                     const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4110                     mz_uint32 field_data_remaining = field_data_size;
4111 
4112                     if (pFound_zip64_extra_data)
4113                         *pFound_zip64_extra_data = MZ_TRUE;
4114 
4115                     if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4116                     {
4117                         if (field_data_remaining < sizeof(mz_uint64))
4118                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4119 
4120                         pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4121                         pField_data += sizeof(mz_uint64);
4122                         field_data_remaining -= sizeof(mz_uint64);
4123                     }
4124 
4125                     if (pStat->m_comp_size == MZ_UINT32_MAX)
4126                     {
4127                         if (field_data_remaining < sizeof(mz_uint64))
4128                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4129 
4130                         pStat->m_comp_size = MZ_READ_LE64(pField_data);
4131                         pField_data += sizeof(mz_uint64);
4132                         field_data_remaining -= sizeof(mz_uint64);
4133                     }
4134 
4135                     if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4136                     {
4137                         if (field_data_remaining < sizeof(mz_uint64))
4138                             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4139 
4140                         pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4141                         pField_data += sizeof(mz_uint64);
4142                         field_data_remaining -= sizeof(mz_uint64);
4143                     }
4144 
4145                     break;
4146                 }
4147 
4148                 pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4149                 extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4150             } while (extra_size_remaining);
4151         }
4152     }
4153 
4154     return MZ_TRUE;
4155 }
4156 
mz_zip_string_equal(const char * pA,const char * pB,mz_uint len,mz_uint flags)4157 static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4158 {
4159     mz_uint i;
4160     if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4161         return 0 == memcmp(pA, pB, len);
4162     for (i = 0; i < len; ++i)
4163         if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4164             return MZ_FALSE;
4165     return MZ_TRUE;
4166 }
4167 
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)4168 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)
4169 {
4170     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;
4171     mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4172     mz_uint8 l = 0, r = 0;
4173     pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4174     pE = pL + MZ_MIN(l_len, r_len);
4175     while (pL < pE)
4176     {
4177         if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4178             break;
4179         pL++;
4180         pR++;
4181     }
4182     return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4183 }
4184 
mz_zip_locate_file_binary_search(mz_zip_archive * pZip,const char * pFilename,mz_uint32 * pIndex)4185 static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4186 {
4187     mz_zip_internal_state *pState = pZip->m_pState;
4188     const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4189     const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4190     mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4191     const uint32_t size = pZip->m_total_files;
4192     const mz_uint filename_len = (mz_uint)strlen(pFilename);
4193 
4194     if (pIndex)
4195         *pIndex = 0;
4196 
4197     if (size)
4198     {
4199         /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
4200         /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
4201         mz_int64 l = 0, h = (mz_int64)size - 1;
4202 
4203         while (l <= h)
4204         {
4205             mz_int64 m = l + ((h - l) >> 1);
4206             uint32_t file_index = pIndices[(uint32_t)m];
4207 
4208             int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4209             if (!comp)
4210             {
4211                 if (pIndex)
4212                     *pIndex = file_index;
4213                 return MZ_TRUE;
4214             }
4215             else if (comp < 0)
4216                 l = m + 1;
4217             else
4218                 h = m - 1;
4219         }
4220     }
4221 
4222     return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4223 }
4224 
mz_zip_reader_locate_file(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags)4225 int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4226 {
4227     mz_uint32 index;
4228     if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4229         return -1;
4230     else
4231         return (int)index;
4232 }
4233 
mz_zip_reader_locate_file_v2(mz_zip_archive * pZip,const char * pName,const char * pComment,mz_uint flags,mz_uint32 * pIndex)4234 mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4235 {
4236     mz_uint file_index;
4237     size_t name_len, comment_len;
4238 
4239     if (pIndex)
4240         *pIndex = 0;
4241 
4242     if ((!pZip) || (!pZip->m_pState) || (!pName))
4243         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4244 
4245     /* See if we can use a binary search */
4246     if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
4247         (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4248         ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
4249     {
4250         return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4251     }
4252 
4253     /* Locate the entry by scanning the entire central directory */
4254     name_len = strlen(pName);
4255     if (name_len > MZ_UINT16_MAX)
4256         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4257 
4258     comment_len = pComment ? strlen(pComment) : 0;
4259     if (comment_len > MZ_UINT16_MAX)
4260         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4261 
4262     for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4263     {
4264         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));
4265         mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4266         const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4267         if (filename_len < name_len)
4268             continue;
4269         if (comment_len)
4270         {
4271             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);
4272             const char *pFile_comment = pFilename + filename_len + file_extra_len;
4273             if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4274                 continue;
4275         }
4276         if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4277         {
4278             int ofs = filename_len - 1;
4279             do
4280             {
4281                 if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4282                     break;
4283             } while (--ofs >= 0);
4284             ofs++;
4285             pFilename += ofs;
4286             filename_len -= ofs;
4287         }
4288         if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4289         {
4290             if (pIndex)
4291                 *pIndex = file_index;
4292             return MZ_TRUE;
4293         }
4294     }
4295 
4296     return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4297 }
4298 
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)4299 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)
4300 {
4301     int status = TINFL_STATUS_DONE;
4302     mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4303     mz_zip_archive_file_stat file_stat;
4304     void *pRead_buf;
4305     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4306     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4307     tinfl_decompressor inflator;
4308 
4309     if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4310         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4311 
4312     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4313         return MZ_FALSE;
4314 
4315     /* A directory or zero length file */
4316     if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4317         return MZ_TRUE;
4318 
4319     /* Encryption and patch files are not supported. */
4320     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))
4321         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4322 
4323     /* This function only supports decompressing stored and deflate. */
4324     if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4325         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4326 
4327     /* Ensure supplied output buffer is large enough. */
4328     needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4329     if (buf_size < needed_size)
4330         return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
4331 
4332     /* Read and parse the local directory entry. */
4333     cur_file_ofs = file_stat.m_local_header_ofs;
4334     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)
4335         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4336 
4337     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4338         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4339 
4340     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);
4341     if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4342         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4343 
4344     if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4345     {
4346         /* The file is stored or the caller has requested the compressed data. */
4347         if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4348             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4349 
4350 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4351         if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4352         {
4353             if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4354                 return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4355         }
4356 #endif
4357 
4358         return MZ_TRUE;
4359     }
4360 
4361     /* Decompress the file either directly from memory or from a file input buffer. */
4362     tinfl_init(&inflator);
4363 
4364     if (pZip->m_pState->m_pMem)
4365     {
4366         /* Read directly from the archive in memory. */
4367         pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4368         read_buf_size = read_buf_avail = file_stat.m_comp_size;
4369         comp_remaining = 0;
4370     }
4371     else if (pUser_read_buf)
4372     {
4373         /* Use a user provided read buffer. */
4374         if (!user_read_buf_size)
4375             return MZ_FALSE;
4376         pRead_buf = (mz_uint8 *)pUser_read_buf;
4377         read_buf_size = user_read_buf_size;
4378         read_buf_avail = 0;
4379         comp_remaining = file_stat.m_comp_size;
4380     }
4381     else
4382     {
4383         /* Temporarily allocate a read buffer. */
4384         read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4385         if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4386             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4387 
4388         if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4389             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4390 
4391         read_buf_avail = 0;
4392         comp_remaining = file_stat.m_comp_size;
4393     }
4394 
4395     do
4396     {
4397         /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
4398         size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4399         if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4400         {
4401             read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4402             if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4403             {
4404                 status = TINFL_STATUS_FAILED;
4405                 mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4406                 break;
4407             }
4408             cur_file_ofs += read_buf_avail;
4409             comp_remaining -= read_buf_avail;
4410             read_buf_ofs = 0;
4411         }
4412         in_buf_size = (size_t)read_buf_avail;
4413         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));
4414         read_buf_avail -= in_buf_size;
4415         read_buf_ofs += in_buf_size;
4416         out_buf_ofs += out_buf_size;
4417     } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4418 
4419     if (status == TINFL_STATUS_DONE)
4420     {
4421         /* Make sure the entire file was decompressed, and check its CRC. */
4422         if (out_buf_ofs != file_stat.m_uncomp_size)
4423         {
4424             mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4425             status = TINFL_STATUS_FAILED;
4426         }
4427 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4428         else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4429         {
4430             mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4431             status = TINFL_STATUS_FAILED;
4432         }
4433 #endif
4434     }
4435 
4436     if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4437         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4438 
4439     return status == TINFL_STATUS_DONE;
4440 }
4441 
mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags,void * pUser_read_buf,size_t user_read_buf_size)4442 mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size)
4443 {
4444     mz_uint32 file_index;
4445     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4446         return MZ_FALSE;
4447     return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
4448 }
4449 
mz_zip_reader_extract_to_mem(mz_zip_archive * pZip,mz_uint file_index,void * pBuf,size_t buf_size,mz_uint flags)4450 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)
4451 {
4452     return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
4453 }
4454 
mz_zip_reader_extract_file_to_mem(mz_zip_archive * pZip,const char * pFilename,void * pBuf,size_t buf_size,mz_uint flags)4455 mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags)
4456 {
4457     return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4458 }
4459 
mz_zip_reader_extract_to_heap(mz_zip_archive * pZip,mz_uint file_index,size_t * pSize,mz_uint flags)4460 void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4461 {
4462     mz_uint64 comp_size, uncomp_size, alloc_size;
4463     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4464     void *pBuf;
4465 
4466     if (pSize)
4467         *pSize = 0;
4468 
4469     if (!p)
4470     {
4471         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4472         return NULL;
4473     }
4474 
4475     comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4476     uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4477 
4478     alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
4479     if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4480     {
4481         mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4482         return NULL;
4483     }
4484 
4485     if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4486     {
4487         mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4488         return NULL;
4489     }
4490 
4491     if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
4492     {
4493         pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4494         return NULL;
4495     }
4496 
4497     if (pSize)
4498         *pSize = (size_t)alloc_size;
4499     return pBuf;
4500 }
4501 
mz_zip_reader_extract_file_to_heap(mz_zip_archive * pZip,const char * pFilename,size_t * pSize,mz_uint flags)4502 void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4503 {
4504     mz_uint32 file_index;
4505     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4506     {
4507         if (pSize)
4508             *pSize = 0;
4509         return MZ_FALSE;
4510     }
4511     return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4512 }
4513 
mz_zip_reader_extract_to_callback(mz_zip_archive * pZip,mz_uint file_index,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)4514 mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4515 {
4516     int status = TINFL_STATUS_DONE;
4517     mz_uint file_crc32 = MZ_CRC32_INIT;
4518     mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4519     mz_zip_archive_file_stat file_stat;
4520     void *pRead_buf = NULL;
4521     void *pWrite_buf = NULL;
4522     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4523     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4524 
4525     if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4526         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4527 
4528     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4529         return MZ_FALSE;
4530 
4531     /* A directory or zero length file */
4532     if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4533         return MZ_TRUE;
4534 
4535     /* Encryption and patch files are not supported. */
4536     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))
4537         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4538 
4539     /* This function only supports decompressing stored and deflate. */
4540     if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4541         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4542 
4543     /* Read and do some minimal validation of the local directory entry (this doesn't crack the zip64 stuff, which we already have from the central dir) */
4544     cur_file_ofs = file_stat.m_local_header_ofs;
4545     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)
4546         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4547 
4548     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4549         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4550 
4551     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);
4552     if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4553         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4554 
4555     /* Decompress the file either directly from memory or from a file input buffer. */
4556     if (pZip->m_pState->m_pMem)
4557     {
4558         pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4559         read_buf_size = read_buf_avail = file_stat.m_comp_size;
4560         comp_remaining = 0;
4561     }
4562     else
4563     {
4564         read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4565         if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4566             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4567 
4568         read_buf_avail = 0;
4569         comp_remaining = file_stat.m_comp_size;
4570     }
4571 
4572     if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4573     {
4574         /* The file is stored or the caller has requested the compressed data. */
4575         if (pZip->m_pState->m_pMem)
4576         {
4577             if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4578                 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4579 
4580             if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4581             {
4582                 mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4583                 status = TINFL_STATUS_FAILED;
4584             }
4585             else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4586             {
4587 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4588                 file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4589 #endif
4590             }
4591 
4592             cur_file_ofs += file_stat.m_comp_size;
4593             out_buf_ofs += file_stat.m_comp_size;
4594             comp_remaining = 0;
4595         }
4596         else
4597         {
4598             while (comp_remaining)
4599             {
4600                 read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4601                 if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4602                 {
4603                     mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4604                     status = TINFL_STATUS_FAILED;
4605                     break;
4606                 }
4607 
4608 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4609                 if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4610                 {
4611                     file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4612                 }
4613 #endif
4614 
4615                 if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4616                 {
4617                     mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4618                     status = TINFL_STATUS_FAILED;
4619                     break;
4620                 }
4621 
4622                 cur_file_ofs += read_buf_avail;
4623                 out_buf_ofs += read_buf_avail;
4624                 comp_remaining -= read_buf_avail;
4625             }
4626         }
4627     }
4628     else
4629     {
4630         tinfl_decompressor inflator;
4631         tinfl_init(&inflator);
4632 
4633         if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4634         {
4635             mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4636             status = TINFL_STATUS_FAILED;
4637         }
4638         else
4639         {
4640             do
4641             {
4642                 mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4643                 size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4644                 if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4645                 {
4646                     read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4647                     if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4648                     {
4649                         mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4650                         status = TINFL_STATUS_FAILED;
4651                         break;
4652                     }
4653                     cur_file_ofs += read_buf_avail;
4654                     comp_remaining -= read_buf_avail;
4655                     read_buf_ofs = 0;
4656                 }
4657 
4658                 in_buf_size = (size_t)read_buf_avail;
4659                 status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
4660                 read_buf_avail -= in_buf_size;
4661                 read_buf_ofs += in_buf_size;
4662 
4663                 if (out_buf_size)
4664                 {
4665                     if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4666                     {
4667                         mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4668                         status = TINFL_STATUS_FAILED;
4669                         break;
4670                     }
4671 
4672 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4673                     file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4674 #endif
4675                     if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4676                     {
4677                         mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4678                         status = TINFL_STATUS_FAILED;
4679                         break;
4680                     }
4681                 }
4682             } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4683         }
4684     }
4685 
4686     if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4687     {
4688         /* Make sure the entire file was decompressed, and check its CRC. */
4689         if (out_buf_ofs != file_stat.m_uncomp_size)
4690         {
4691             mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4692             status = TINFL_STATUS_FAILED;
4693         }
4694 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4695         else if (file_crc32 != file_stat.m_crc32)
4696         {
4697             mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4698             status = TINFL_STATUS_FAILED;
4699         }
4700 #endif
4701     }
4702 
4703     if (!pZip->m_pState->m_pMem)
4704         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4705 
4706     if (pWrite_buf)
4707         pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4708 
4709     return status == TINFL_STATUS_DONE;
4710 }
4711 
mz_zip_reader_extract_file_to_callback(mz_zip_archive * pZip,const char * pFilename,mz_file_write_func pCallback,void * pOpaque,mz_uint flags)4712 mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags)
4713 {
4714     mz_uint32 file_index;
4715     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4716         return MZ_FALSE;
4717 
4718     return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4719 }
4720 
mz_zip_reader_extract_iter_new(mz_zip_archive * pZip,mz_uint file_index,mz_uint flags)4721 mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
4722 {
4723     mz_zip_reader_extract_iter_state *pState;
4724     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4725     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4726 
4727     /* Argument sanity check */
4728     if ((!pZip) || (!pZip->m_pState))
4729         return NULL;
4730 
4731     /* Allocate an iterator status structure */
4732     pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
4733     if (!pState)
4734     {
4735         mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4736         return NULL;
4737     }
4738 
4739     /* Fetch file details */
4740     if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
4741     {
4742         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4743         return NULL;
4744     }
4745 
4746     /* Encryption and patch files are not supported. */
4747     if (pState->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))
4748     {
4749         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4750         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4751         return NULL;
4752     }
4753 
4754     /* This function only supports decompressing stored and deflate. */
4755     if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
4756     {
4757         mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4758         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4759         return NULL;
4760     }
4761 
4762     /* Init state - save args */
4763     pState->pZip = pZip;
4764     pState->flags = flags;
4765 
4766     /* Init state - reset variables to defaults */
4767     pState->status = TINFL_STATUS_DONE;
4768 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4769     pState->file_crc32 = MZ_CRC32_INIT;
4770 #endif
4771     pState->read_buf_ofs = 0;
4772     pState->out_buf_ofs = 0;
4773     pState->pRead_buf = NULL;
4774     pState->pWrite_buf = NULL;
4775     pState->out_blk_remain = 0;
4776 
4777     /* Read and parse the local directory entry. */
4778     pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
4779     if (pZip->m_pRead(pZip->m_pIO_opaque, pState->cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
4780     {
4781         mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4782         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4783         return NULL;
4784     }
4785 
4786     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4787     {
4788         mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4789         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4790         return NULL;
4791     }
4792 
4793     pState->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);
4794     if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
4795     {
4796         mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4797         pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4798         return NULL;
4799     }
4800 
4801     /* Decompress the file either directly from memory or from a file input buffer. */
4802     if (pZip->m_pState->m_pMem)
4803     {
4804         pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
4805         pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
4806         pState->comp_remaining = pState->file_stat.m_comp_size;
4807     }
4808     else
4809     {
4810         if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4811         {
4812             /* Decompression required, therefore intermediate read buffer required */
4813             pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
4814             if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
4815             {
4816                 mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4817                 pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4818                 return NULL;
4819             }
4820         }
4821         else
4822         {
4823             /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
4824             pState->read_buf_size = 0;
4825         }
4826         pState->read_buf_avail = 0;
4827         pState->comp_remaining = pState->file_stat.m_comp_size;
4828     }
4829 
4830     if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
4831     {
4832         /* Decompression required, init decompressor */
4833         tinfl_init( &pState->inflator );
4834 
4835         /* Allocate write buffer */
4836         if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4837         {
4838             mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4839             if (pState->pRead_buf)
4840                 pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
4841             pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4842             return NULL;
4843         }
4844     }
4845 
4846     return pState;
4847 }
4848 
mz_zip_reader_extract_file_iter_new(mz_zip_archive * pZip,const char * pFilename,mz_uint flags)4849 mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
4850 {
4851     mz_uint32 file_index;
4852 
4853     /* Locate file index by name */
4854     if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4855         return NULL;
4856 
4857     /* Construct iterator */
4858     return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
4859 }
4860 
mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state * pState,void * pvBuf,size_t buf_size)4861 size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)
4862 {
4863     size_t copied_to_caller = 0;
4864 
4865     /* Argument sanity check */
4866     if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
4867         return 0;
4868 
4869     if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
4870     {
4871         /* The file is stored or the caller has requested the compressed data, calc amount to return. */
4872         copied_to_caller = MZ_MIN( buf_size, pState->comp_remaining );
4873 
4874         /* Zip is in memory....or requires reading from a file? */
4875         if (pState->pZip->m_pState->m_pMem)
4876         {
4877             /* Copy data to caller's buffer */
4878             memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
4879             pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
4880         }
4881         else
4882         {
4883             /* Read directly into caller's buffer */
4884             if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
4885             {
4886                 /* Failed to read all that was asked for, flag failure and alert user */
4887                 mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
4888                 pState->status = TINFL_STATUS_FAILED;
4889                 copied_to_caller = 0;
4890             }
4891         }
4892 
4893 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4894         /* Compute CRC if not returning compressed data only */
4895         if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4896             pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
4897 #endif
4898 
4899         /* Advance offsets, dec counters */
4900         pState->cur_file_ofs += copied_to_caller;
4901         pState->out_buf_ofs += copied_to_caller;
4902         pState->comp_remaining -= copied_to_caller;
4903     }
4904     else
4905     {
4906         do
4907         {
4908             /* Calc ptr to write buffer - given current output pos and block size */
4909             mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4910 
4911             /* Calc max output size - given current output pos and block size */
4912             size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4913 
4914             if (!pState->out_blk_remain)
4915             {
4916                 /* Read more data from file if none available (and reading from file) */
4917                 if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
4918                 {
4919                     /* Calc read size */
4920                     pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
4921                     if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pState->pRead_buf, (size_t)pState->read_buf_avail) != pState->read_buf_avail)
4922                     {
4923                         mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
4924                         pState->status = TINFL_STATUS_FAILED;
4925                         break;
4926                     }
4927 
4928                     /* Advance offsets, dec counters */
4929                     pState->cur_file_ofs += pState->read_buf_avail;
4930                     pState->comp_remaining -= pState->read_buf_avail;
4931                     pState->read_buf_ofs = 0;
4932                 }
4933 
4934                 /* Perform decompression */
4935                 in_buf_size = (size_t)pState->read_buf_avail;
4936                 pState->status = tinfl_decompress(&pState->inflator, (const mz_uint8 *)pState->pRead_buf + pState->read_buf_ofs, &in_buf_size, (mz_uint8 *)pState->pWrite_buf, pWrite_buf_cur, &out_buf_size, pState->comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0);
4937                 pState->read_buf_avail -= in_buf_size;
4938                 pState->read_buf_ofs += in_buf_size;
4939 
4940                 /* Update current output block size remaining */
4941                 pState->out_blk_remain = out_buf_size;
4942             }
4943 
4944             if (pState->out_blk_remain)
4945             {
4946                 /* Calc amount to return. */
4947                 size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
4948 
4949                 /* Copy data to caller's buffer */
4950                 memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
4951 
4952 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4953                 /* Perform CRC */
4954                 pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
4955 #endif
4956 
4957                 /* Decrement data consumed from block */
4958                 pState->out_blk_remain -= to_copy;
4959 
4960                 /* Inc output offset, while performing sanity check */
4961                 if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
4962                 {
4963                     mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4964                     pState->status = TINFL_STATUS_FAILED;
4965                     break;
4966                 }
4967 
4968                 /* Increment counter of data copied to caller */
4969                 copied_to_caller += to_copy;
4970             }
4971         } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
4972     }
4973 
4974     /* Return how many bytes were copied into user buffer */
4975     return copied_to_caller;
4976 }
4977 
mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state * pState)4978 mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState)
4979 {
4980     int status;
4981 
4982     /* Argument sanity check */
4983     if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
4984         return MZ_FALSE;
4985 
4986     /* Was decompression completed and requested? */
4987     if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4988     {
4989         /* Make sure the entire file was decompressed, and check its CRC. */
4990         if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
4991         {
4992             mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4993             pState->status = TINFL_STATUS_FAILED;
4994         }
4995 #ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4996         else if (pState->file_crc32 != pState->file_stat.m_crc32)
4997         {
4998             mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4999             pState->status = TINFL_STATUS_FAILED;
5000         }
5001 #endif
5002     }
5003 
5004     /* Free buffers */
5005     if (!pState->pZip->m_pState->m_pMem)
5006         pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5007     if (pState->pWrite_buf)
5008         pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5009 
5010     /* Save status */
5011     status = pState->status;
5012 
5013     /* Free context */
5014     pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5015 
5016     return status == TINFL_STATUS_DONE;
5017 }
5018 
5019 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_callback(void * pOpaque,mz_uint64 ofs,const void * pBuf,size_t n)5020 static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
5021 {
5022     (void)ofs;
5023 
5024     return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5025 }
5026 
mz_zip_reader_extract_to_file(mz_zip_archive * pZip,mz_uint file_index,const char * pDst_filename,mz_uint flags)5027 mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
5028 {
5029     mz_bool status;
5030     mz_zip_archive_file_stat file_stat;
5031     MZ_FILE *pFile;
5032 
5033     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5034         return MZ_FALSE;
5035 
5036     if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5037         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5038 
5039     pFile = MZ_FOPEN(pDst_filename, "wb");
5040     if (!pFile)
5041         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5042 
5043     status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5044 
5045     if (MZ_FCLOSE(pFile) == EOF)
5046     {
5047         if (status)
5048             mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5049 
5050         status = MZ_FALSE;
5051     }
5052 
5053 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5054     if (status)
5055         mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5056 #endif
5057 
5058     return status;
5059 }
5060 
mz_zip_reader_extract_file_to_file(mz_zip_archive * pZip,const char * pArchive_filename,const char * pDst_filename,mz_uint flags)5061 mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
5062 {
5063     mz_uint32 file_index;
5064     if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5065         return MZ_FALSE;
5066 
5067     return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5068 }
5069 
mz_zip_reader_extract_to_cfile(mz_zip_archive * pZip,mz_uint file_index,MZ_FILE * pFile,mz_uint flags)5070 mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
5071 {
5072     mz_zip_archive_file_stat file_stat;
5073 
5074     if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5075         return MZ_FALSE;
5076 
5077     if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5078         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5079 
5080     return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5081 }
5082 
mz_zip_reader_extract_file_to_cfile(mz_zip_archive * pZip,const char * pArchive_filename,MZ_FILE * pFile,mz_uint flags)5083 mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
5084 {
5085     mz_uint32 file_index;
5086     if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5087         return MZ_FALSE;
5088 
5089     return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5090 }
5091 #endif /* #ifndef MINIZ_NO_STDIO */
5092 
mz_zip_compute_crc32_callback(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5093 static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5094 {
5095     mz_uint32 *p = (mz_uint32 *)pOpaque;
5096     (void)file_ofs;
5097     *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
5098     return n;
5099 }
5100 
mz_zip_validate_file(mz_zip_archive * pZip,mz_uint file_index,mz_uint flags)5101 mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
5102 {
5103     mz_zip_archive_file_stat file_stat;
5104     mz_zip_internal_state *pState;
5105     const mz_uint8 *pCentral_dir_header;
5106     mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5107     mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5108     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
5109     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5110     mz_uint64 local_header_ofs = 0;
5111     mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5112     mz_uint64 local_header_comp_size, local_header_uncomp_size;
5113     mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5114     mz_bool has_data_descriptor;
5115     mz_uint32 local_header_bit_flags;
5116 
5117     mz_zip_array file_data_array;
5118     mz_zip_array_init(&file_data_array, 1);
5119 
5120     if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5121         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5122 
5123     if (file_index > pZip->m_total_files)
5124         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5125 
5126     pState = pZip->m_pState;
5127 
5128     pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5129 
5130     if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5131         return MZ_FALSE;
5132 
5133     /* A directory or zero length file */
5134     if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5135         return MZ_TRUE;
5136 
5137     /* Encryption and patch files are not supported. */
5138     if (file_stat.m_is_encrypted)
5139         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5140 
5141     /* This function only supports stored and deflate. */
5142     if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5143         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5144 
5145     if (!file_stat.m_is_supported)
5146         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5147 
5148     /* Read and parse the local directory entry. */
5149     local_header_ofs = file_stat.m_local_header_ofs;
5150     if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
5151         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5152 
5153     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5154         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5155 
5156     local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5157     local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5158     local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5159     local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5160     local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5161     local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5162     has_data_descriptor = (local_header_bit_flags & 8) != 0;
5163 
5164     if (local_header_filename_len != strlen(file_stat.m_filename))
5165         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5166 
5167     if ((local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size) > pZip->m_archive_size)
5168         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5169 
5170     if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5171         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5172 
5173     if (local_header_filename_len)
5174     {
5175         if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE, file_data_array.m_p, local_header_filename_len) != local_header_filename_len)
5176         {
5177             mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5178             goto handle_failure;
5179         }
5180 
5181         /* I've seen 1 archive that had the same pathname, but used backslashes in the local dir and forward slashes in the central dir. Do we care about this? For now, this case will fail validation. */
5182         if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5183         {
5184             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5185             goto handle_failure;
5186         }
5187     }
5188 
5189     if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5190     {
5191         mz_uint32 extra_size_remaining = local_header_extra_len;
5192         const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
5193 
5194         if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
5195         {
5196             mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5197             goto handle_failure;
5198         }
5199 
5200         do
5201         {
5202             mz_uint32 field_id, field_data_size, field_total_size;
5203 
5204             if (extra_size_remaining < (sizeof(mz_uint16) * 2))
5205                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5206 
5207             field_id = MZ_READ_LE16(pExtra_data);
5208             field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5209             field_total_size = field_data_size + sizeof(mz_uint16) * 2;
5210 
5211             if (field_total_size > extra_size_remaining)
5212                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5213 
5214             if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
5215             {
5216                 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
5217 
5218                 if (field_data_size < sizeof(mz_uint64) * 2)
5219                 {
5220                     mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5221                     goto handle_failure;
5222                 }
5223 
5224                 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5225                 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
5226 
5227                 found_zip64_ext_data_in_ldir = MZ_TRUE;
5228                 break;
5229             }
5230 
5231             pExtra_data += field_total_size;
5232             extra_size_remaining -= field_total_size;
5233         } while (extra_size_remaining);
5234     }
5235 
5236     /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
5237     /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
5238     if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5239     {
5240         mz_uint8 descriptor_buf[32];
5241         mz_bool has_id;
5242         const mz_uint8 *pSrc;
5243         mz_uint32 file_crc32;
5244         mz_uint64 comp_size = 0, uncomp_size = 0;
5245 
5246         mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5247 
5248         if (pZip->m_pRead(pZip->m_pIO_opaque, local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_len + local_header_extra_len + file_stat.m_comp_size, descriptor_buf, sizeof(mz_uint32) * num_descriptor_uint32s) != (sizeof(mz_uint32) * num_descriptor_uint32s))
5249         {
5250             mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5251             goto handle_failure;
5252         }
5253 
5254         has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5255         pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
5256 
5257         file_crc32 = MZ_READ_LE32(pSrc);
5258 
5259         if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5260         {
5261             comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
5262             uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
5263         }
5264         else
5265         {
5266             comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
5267             uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
5268         }
5269 
5270         if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5271         {
5272             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5273             goto handle_failure;
5274         }
5275     }
5276     else
5277     {
5278         if ((local_header_crc32 != file_stat.m_crc32) || (local_header_comp_size != file_stat.m_comp_size) || (local_header_uncomp_size != file_stat.m_uncomp_size))
5279         {
5280             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5281             goto handle_failure;
5282         }
5283     }
5284 
5285     mz_zip_array_clear(pZip, &file_data_array);
5286 
5287     if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5288     {
5289         if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5290             return MZ_FALSE;
5291 
5292         /* 1 more check to be sure, although the extract checks too. */
5293         if (uncomp_crc32 != file_stat.m_crc32)
5294         {
5295             mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5296             return MZ_FALSE;
5297         }
5298     }
5299 
5300     return MZ_TRUE;
5301 
5302 handle_failure:
5303     mz_zip_array_clear(pZip, &file_data_array);
5304     return MZ_FALSE;
5305 }
5306 
mz_zip_validate_archive(mz_zip_archive * pZip,mz_uint flags)5307 mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
5308 {
5309     mz_zip_internal_state *pState;
5310     uint32_t i;
5311 
5312     if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5313         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5314 
5315     pState = pZip->m_pState;
5316 
5317     /* Basic sanity checks */
5318     if (!pState->m_zip64)
5319     {
5320         if (pZip->m_total_files > MZ_UINT16_MAX)
5321             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5322 
5323         if (pZip->m_archive_size > MZ_UINT32_MAX)
5324             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5325     }
5326     else
5327     {
5328         if (pZip->m_total_files >= MZ_UINT32_MAX)
5329             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5330 
5331         if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5332             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5333     }
5334 
5335     for (i = 0; i < pZip->m_total_files; i++)
5336     {
5337         if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
5338         {
5339             mz_uint32 found_index;
5340             mz_zip_archive_file_stat stat;
5341 
5342             if (!mz_zip_reader_file_stat(pZip, i, &stat))
5343                 return MZ_FALSE;
5344 
5345             if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5346                 return MZ_FALSE;
5347 
5348             /* This check can fail if there are duplicate filenames in the archive (which we don't check for when writing - that's up to the user) */
5349             if (found_index != i)
5350                 return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5351         }
5352 
5353         if (!mz_zip_validate_file(pZip, i, flags))
5354             return MZ_FALSE;
5355     }
5356 
5357     return MZ_TRUE;
5358 }
5359 
mz_zip_validate_mem_archive(const void * pMem,size_t size,mz_uint flags,mz_zip_error * pErr)5360 mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5361 {
5362     mz_bool success = MZ_TRUE;
5363     mz_zip_archive zip;
5364     mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5365 
5366     if ((!pMem) || (!size))
5367     {
5368         if (pErr)
5369             *pErr = MZ_ZIP_INVALID_PARAMETER;
5370         return MZ_FALSE;
5371     }
5372 
5373     mz_zip_zero_struct(&zip);
5374 
5375     if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5376     {
5377         if (pErr)
5378             *pErr = zip.m_last_error;
5379         return MZ_FALSE;
5380     }
5381 
5382     if (!mz_zip_validate_archive(&zip, flags))
5383     {
5384         actual_err = zip.m_last_error;
5385         success = MZ_FALSE;
5386     }
5387 
5388     if (!mz_zip_reader_end_internal(&zip, success))
5389     {
5390         if (!actual_err)
5391             actual_err = zip.m_last_error;
5392         success = MZ_FALSE;
5393     }
5394 
5395     if (pErr)
5396         *pErr = actual_err;
5397 
5398     return success;
5399 }
5400 
5401 #ifndef MINIZ_NO_STDIO
mz_zip_validate_file_archive(const char * pFilename,mz_uint flags,mz_zip_error * pErr)5402 mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5403 {
5404     mz_bool success = MZ_TRUE;
5405     mz_zip_archive zip;
5406     mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5407 
5408     if (!pFilename)
5409     {
5410         if (pErr)
5411             *pErr = MZ_ZIP_INVALID_PARAMETER;
5412         return MZ_FALSE;
5413     }
5414 
5415     mz_zip_zero_struct(&zip);
5416 
5417     if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5418     {
5419         if (pErr)
5420             *pErr = zip.m_last_error;
5421         return MZ_FALSE;
5422     }
5423 
5424     if (!mz_zip_validate_archive(&zip, flags))
5425     {
5426         actual_err = zip.m_last_error;
5427         success = MZ_FALSE;
5428     }
5429 
5430     if (!mz_zip_reader_end_internal(&zip, success))
5431     {
5432         if (!actual_err)
5433             actual_err = zip.m_last_error;
5434         success = MZ_FALSE;
5435     }
5436 
5437     if (pErr)
5438         *pErr = actual_err;
5439 
5440     return success;
5441 }
5442 #endif /* #ifndef MINIZ_NO_STDIO */
5443 
5444 /* ------------------- .ZIP archive writing */
5445 
5446 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5447 
mz_write_le16(mz_uint8 * p,mz_uint16 v)5448 static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
5449 {
5450     p[0] = (mz_uint8)v;
5451     p[1] = (mz_uint8)(v >> 8);
5452 }
mz_write_le32(mz_uint8 * p,mz_uint32 v)5453 static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
5454 {
5455     p[0] = (mz_uint8)v;
5456     p[1] = (mz_uint8)(v >> 8);
5457     p[2] = (mz_uint8)(v >> 16);
5458     p[3] = (mz_uint8)(v >> 24);
5459 }
mz_write_le64(mz_uint8 * p,mz_uint64 v)5460 static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
5461 {
5462     mz_write_le32(p, (mz_uint32)v);
5463     mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5464 }
5465 
5466 #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5467 #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5468 #define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5469 
mz_zip_heap_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5470 static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5471 {
5472     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5473     mz_zip_internal_state *pState = pZip->m_pState;
5474     mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5475 
5476     if (!n)
5477         return 0;
5478 
5479     /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5480     if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5481     {
5482         mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5483         return 0;
5484     }
5485 
5486     if (new_size > pState->m_mem_capacity)
5487     {
5488         void *pNew_block;
5489         size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5490 
5491         while (new_capacity < new_size)
5492             new_capacity *= 2;
5493 
5494         if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5495         {
5496             mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5497             return 0;
5498         }
5499 
5500         pState->m_pMem = pNew_block;
5501         pState->m_mem_capacity = new_capacity;
5502     }
5503     memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5504     pState->m_mem_size = (size_t)new_size;
5505     return n;
5506 }
5507 
mz_zip_writer_end_internal(mz_zip_archive * pZip,mz_bool set_last_error)5508 static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
5509 {
5510     mz_zip_internal_state *pState;
5511     mz_bool status = MZ_TRUE;
5512 
5513     if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED)))
5514     {
5515         if (set_last_error)
5516             mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5517         return MZ_FALSE;
5518     }
5519 
5520     pState = pZip->m_pState;
5521     pZip->m_pState = NULL;
5522     mz_zip_array_clear(pZip, &pState->m_central_dir);
5523     mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5524     mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5525 
5526 #ifndef MINIZ_NO_STDIO
5527     if (pState->m_pFile)
5528     {
5529         if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5530         {
5531             if (MZ_FCLOSE(pState->m_pFile) == EOF)
5532             {
5533                 if (set_last_error)
5534                     mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5535                 status = MZ_FALSE;
5536             }
5537         }
5538 
5539         pState->m_pFile = NULL;
5540     }
5541 #endif /* #ifndef MINIZ_NO_STDIO */
5542 
5543     if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5544     {
5545         pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5546         pState->m_pMem = NULL;
5547     }
5548 
5549     pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5550     pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5551     return status;
5552 }
5553 
mz_zip_writer_init_v2(mz_zip_archive * pZip,mz_uint64 existing_size,mz_uint flags)5554 mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
5555 {
5556     mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5557 
5558     if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5559         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5560 
5561     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5562     {
5563         if (!pZip->m_pRead)
5564             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5565     }
5566 
5567     if (pZip->m_file_offset_alignment)
5568     {
5569         /* Ensure user specified file offset alignment is a power of 2. */
5570         if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5571             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5572     }
5573 
5574     if (!pZip->m_pAlloc)
5575         pZip->m_pAlloc = miniz_def_alloc_func;
5576     if (!pZip->m_pFree)
5577         pZip->m_pFree = miniz_def_free_func;
5578     if (!pZip->m_pRealloc)
5579         pZip->m_pRealloc = miniz_def_realloc_func;
5580 
5581     pZip->m_archive_size = existing_size;
5582     pZip->m_central_directory_file_ofs = 0;
5583     pZip->m_total_files = 0;
5584 
5585     if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5586         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5587 
5588     memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5589 
5590     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
5591     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
5592     MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
5593 
5594     pZip->m_pState->m_zip64 = zip64;
5595     pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
5596 
5597     pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5598     pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5599 
5600     return MZ_TRUE;
5601 }
5602 
mz_zip_writer_init(mz_zip_archive * pZip,mz_uint64 existing_size)5603 mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
5604 {
5605     return mz_zip_writer_init_v2(pZip, existing_size, 0);
5606 }
5607 
mz_zip_writer_init_heap_v2(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size,mz_uint flags)5608 mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags)
5609 {
5610     pZip->m_pWrite = mz_zip_heap_write_func;
5611     pZip->m_pNeeds_keepalive = NULL;
5612 
5613     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5614         pZip->m_pRead = mz_zip_mem_read_func;
5615 
5616     pZip->m_pIO_opaque = pZip;
5617 
5618     if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5619         return MZ_FALSE;
5620 
5621     pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
5622 
5623     if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5624     {
5625         if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5626         {
5627             mz_zip_writer_end_internal(pZip, MZ_FALSE);
5628             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5629         }
5630         pZip->m_pState->m_mem_capacity = initial_allocation_size;
5631     }
5632 
5633     return MZ_TRUE;
5634 }
5635 
mz_zip_writer_init_heap(mz_zip_archive * pZip,size_t size_to_reserve_at_beginning,size_t initial_allocation_size)5636 mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
5637 {
5638     return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5639 }
5640 
5641 #ifndef MINIZ_NO_STDIO
mz_zip_file_write_func(void * pOpaque,mz_uint64 file_ofs,const void * pBuf,size_t n)5642 static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5643 {
5644     mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5645     mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5646 
5647     file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5648 
5649     if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET))))
5650     {
5651         mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5652         return 0;
5653     }
5654 
5655     return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5656 }
5657 
mz_zip_writer_init_file(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning)5658 mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5659 {
5660     return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5661 }
5662 
mz_zip_writer_init_file_v2(mz_zip_archive * pZip,const char * pFilename,mz_uint64 size_to_reserve_at_beginning,mz_uint flags)5663 mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags)
5664 {
5665     MZ_FILE *pFile;
5666 
5667     pZip->m_pWrite = mz_zip_file_write_func;
5668     pZip->m_pNeeds_keepalive = NULL;
5669 
5670     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5671         pZip->m_pRead = mz_zip_file_read_func;
5672 
5673     pZip->m_pIO_opaque = pZip;
5674 
5675     if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5676         return MZ_FALSE;
5677 
5678     if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5679     {
5680         mz_zip_writer_end(pZip);
5681         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5682     }
5683 
5684     pZip->m_pState->m_pFile = pFile;
5685     pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5686 
5687     if (size_to_reserve_at_beginning)
5688     {
5689         mz_uint64 cur_ofs = 0;
5690         char buf[4096];
5691 
5692         MZ_CLEAR_OBJ(buf);
5693 
5694         do
5695         {
5696             size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5697             if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5698             {
5699                 mz_zip_writer_end(pZip);
5700                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
5701             }
5702             cur_ofs += n;
5703             size_to_reserve_at_beginning -= n;
5704         } while (size_to_reserve_at_beginning);
5705     }
5706 
5707     return MZ_TRUE;
5708 }
5709 
mz_zip_writer_init_cfile(mz_zip_archive * pZip,MZ_FILE * pFile,mz_uint flags)5710 mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
5711 {
5712     pZip->m_pWrite = mz_zip_file_write_func;
5713     pZip->m_pNeeds_keepalive = NULL;
5714 
5715     if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5716         pZip->m_pRead = mz_zip_file_read_func;
5717 
5718     pZip->m_pIO_opaque = pZip;
5719 
5720     if (!mz_zip_writer_init_v2(pZip, 0, flags))
5721         return MZ_FALSE;
5722 
5723     pZip->m_pState->m_pFile = pFile;
5724     pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5725     pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5726 
5727     return MZ_TRUE;
5728 }
5729 #endif /* #ifndef MINIZ_NO_STDIO */
5730 
mz_zip_writer_init_from_reader_v2(mz_zip_archive * pZip,const char * pFilename,mz_uint flags)5731 mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
5732 {
5733     mz_zip_internal_state *pState;
5734 
5735     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5736         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5737 
5738     if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5739     {
5740         /* We don't support converting a non-zip64 file to zip64 - this seems like more trouble than it's worth. (What about the existing 32-bit data descriptors that could follow the compressed data?) */
5741         if (!pZip->m_pState->m_zip64)
5742             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5743     }
5744 
5745     /* No sense in trying to write to an archive that's already at the support max size */
5746     if (pZip->m_pState->m_zip64)
5747     {
5748         if (pZip->m_total_files == MZ_UINT32_MAX)
5749             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5750     }
5751     else
5752     {
5753         if (pZip->m_total_files == MZ_UINT16_MAX)
5754             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5755 
5756         if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
5757             return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5758     }
5759 
5760     pState = pZip->m_pState;
5761 
5762     if (pState->m_pFile)
5763     {
5764 #ifdef MINIZ_NO_STDIO
5765         (void)pFilename;
5766         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5767 #else
5768         if (pZip->m_pIO_opaque != pZip)
5769             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5770 
5771         if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5772         {
5773             if (!pFilename)
5774                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5775 
5776             /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
5777             if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
5778             {
5779                 /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
5780                 mz_zip_reader_end_internal(pZip, MZ_FALSE);
5781                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5782             }
5783         }
5784 
5785         pZip->m_pWrite = mz_zip_file_write_func;
5786         pZip->m_pNeeds_keepalive = NULL;
5787 #endif /* #ifdef MINIZ_NO_STDIO */
5788     }
5789     else if (pState->m_pMem)
5790     {
5791         /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
5792         if (pZip->m_pIO_opaque != pZip)
5793             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5794 
5795         pState->m_mem_capacity = pState->m_mem_size;
5796         pZip->m_pWrite = mz_zip_heap_write_func;
5797         pZip->m_pNeeds_keepalive = NULL;
5798     }
5799     /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
5800     else if (!pZip->m_pWrite)
5801         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5802 
5803     /* Start writing new files at the archive's current central directory location. */
5804     /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
5805     pZip->m_archive_size = pZip->m_central_directory_file_ofs;
5806     pZip->m_central_directory_file_ofs = 0;
5807 
5808     /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
5809     /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
5810     /* TODO: We could easily maintain the sorted central directory offsets. */
5811     mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
5812 
5813     pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5814 
5815     return MZ_TRUE;
5816 }
5817 
mz_zip_writer_init_from_reader(mz_zip_archive * pZip,const char * pFilename)5818 mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
5819 {
5820     return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
5821 }
5822 
5823 /* TODO: pArchive_name is a terrible name here! */
mz_zip_writer_add_mem(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,mz_uint level_and_flags)5824 mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags)
5825 {
5826     return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
5827 }
5828 
5829 typedef struct
5830 {
5831     mz_zip_archive *m_pZip;
5832     mz_uint64 m_cur_archive_file_ofs;
5833     mz_uint64 m_comp_size;
5834 } mz_zip_writer_add_state;
5835 
mz_zip_writer_add_put_buf_callback(const void * pBuf,int len,void * pUser)5836 static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
5837 {
5838     mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
5839     if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
5840         return MZ_FALSE;
5841 
5842     pState->m_cur_archive_file_ofs += len;
5843     pState->m_comp_size += len;
5844     return MZ_TRUE;
5845 }
5846 
5847 #define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
5848 #define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
mz_zip_writer_create_zip64_extra_data(mz_uint8 * pBuf,mz_uint64 * pUncomp_size,mz_uint64 * pComp_size,mz_uint64 * pLocal_header_ofs)5849 static mz_uint32 mz_zip_writer_create_zip64_extra_data(mz_uint8 *pBuf, mz_uint64 *pUncomp_size, mz_uint64 *pComp_size, mz_uint64 *pLocal_header_ofs)
5850 {
5851     mz_uint8 *pDst = pBuf;
5852     mz_uint32 field_size = 0;
5853 
5854     MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
5855     MZ_WRITE_LE16(pDst + 2, 0);
5856     pDst += sizeof(mz_uint16) * 2;
5857 
5858     if (pUncomp_size)
5859     {
5860         MZ_WRITE_LE64(pDst, *pUncomp_size);
5861         pDst += sizeof(mz_uint64);
5862         field_size += sizeof(mz_uint64);
5863     }
5864 
5865     if (pComp_size)
5866     {
5867         MZ_WRITE_LE64(pDst, *pComp_size);
5868         pDst += sizeof(mz_uint64);
5869         field_size += sizeof(mz_uint64);
5870     }
5871 
5872     if (pLocal_header_ofs)
5873     {
5874         MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
5875         pDst += sizeof(mz_uint64);
5876         field_size += sizeof(mz_uint64);
5877     }
5878 
5879     MZ_WRITE_LE16(pBuf + 2, field_size);
5880 
5881     return (mz_uint32)(pDst - pBuf);
5882 }
5883 
mz_zip_writer_create_local_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date)5884 static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date)
5885 {
5886     (void)pZip;
5887     memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
5888     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
5889     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5890     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
5891     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
5892     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
5893     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
5894     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
5895     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
5896     MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
5897     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
5898     MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
5899     return MZ_TRUE;
5900 }
5901 
mz_zip_writer_create_central_dir_header(mz_zip_archive * pZip,mz_uint8 * pDst,mz_uint16 filename_size,mz_uint16 extra_size,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes)5902 static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst,
5903                                                        mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
5904                                                        mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
5905                                                        mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
5906                                                        mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
5907 {
5908     (void)pZip;
5909     memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
5910     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
5911     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
5912     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
5913     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
5914     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
5915     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
5916     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
5917     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
5918     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
5919     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
5920     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
5921     MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
5922     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
5923     MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
5924     return MZ_TRUE;
5925 }
5926 
mz_zip_writer_add_to_central_dir(mz_zip_archive * pZip,const char * pFilename,mz_uint16 filename_size,const void * pExtra,mz_uint16 extra_size,const void * pComment,mz_uint16 comment_size,mz_uint64 uncomp_size,mz_uint64 comp_size,mz_uint32 uncomp_crc32,mz_uint16 method,mz_uint16 bit_flags,mz_uint16 dos_time,mz_uint16 dos_date,mz_uint64 local_header_ofs,mz_uint32 ext_attributes,const char * user_extra_data,mz_uint user_extra_data_len)5927 static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
5928                                                 const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
5929                                                 mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
5930                                                 mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
5931                                                 mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
5932                                                 const char *user_extra_data, mz_uint user_extra_data_len)
5933 {
5934     mz_zip_internal_state *pState = pZip->m_pState;
5935     mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
5936     size_t orig_central_dir_size = pState->m_central_dir.m_size;
5937     mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
5938 
5939     if (!pZip->m_pState->m_zip64)
5940     {
5941         if (local_header_ofs > 0xFFFFFFFF)
5942             return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5943     }
5944 
5945     /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
5946     if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + user_extra_data_len + comment_size) >= MZ_UINT32_MAX)
5947         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
5948 
5949     if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size + user_extra_data_len, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes))
5950         return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
5951 
5952     if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
5953         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
5954         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
5955         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
5956         (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
5957         (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
5958     {
5959         /* Try to resize the central directory array back into its original state. */
5960         mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
5961         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5962     }
5963 
5964     return MZ_TRUE;
5965 }
5966 
mz_zip_writer_validate_archive_name(const char * pArchive_name)5967 static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
5968 {
5969     /* Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. */
5970     if (*pArchive_name == '/')
5971         return MZ_FALSE;
5972 
5973     while (*pArchive_name)
5974     {
5975         if ((*pArchive_name == '\\') || (*pArchive_name == ':'))
5976             return MZ_FALSE;
5977 
5978         pArchive_name++;
5979     }
5980 
5981     return MZ_TRUE;
5982 }
5983 
mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive * pZip)5984 static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
5985 {
5986     mz_uint32 n;
5987     if (!pZip->m_file_offset_alignment)
5988         return 0;
5989     n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
5990     return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
5991 }
5992 
mz_zip_writer_write_zeros(mz_zip_archive * pZip,mz_uint64 cur_file_ofs,mz_uint32 n)5993 static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
5994 {
5995     char buf[4096];
5996     memset(buf, 0, MZ_MIN(sizeof(buf), n));
5997     while (n)
5998     {
5999         mz_uint32 s = MZ_MIN(sizeof(buf), n);
6000         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6001             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6002 
6003         cur_file_ofs += s;
6004         n -= s;
6005     }
6006     return MZ_TRUE;
6007 }
6008 
mz_zip_writer_add_mem_ex(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_uint64 uncomp_size,mz_uint32 uncomp_crc32)6009 mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6010                                  mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
6011 {
6012     return mz_zip_writer_add_mem_ex_v2(pZip, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, uncomp_size, uncomp_crc32, NULL, NULL, 0, NULL, 0);
6013 }
6014 
mz_zip_writer_add_mem_ex_v2(mz_zip_archive * pZip,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_uint64 uncomp_size,mz_uint32 uncomp_crc32,MZ_TIME_T * last_modified,const char * user_extra_data,mz_uint user_extra_data_len,const char * user_extra_data_central,mz_uint user_extra_data_central_len)6015 mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size,
6016                                     mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
6017                                     const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6018 {
6019     mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6020     mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6021     mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6022     size_t archive_name_size;
6023     mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6024     tdefl_compressor *pComp = NULL;
6025     mz_bool store_data_uncompressed;
6026     mz_zip_internal_state *pState;
6027     mz_uint8 *pExtra_data = NULL;
6028     mz_uint32 extra_size = 0;
6029     mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6030     mz_uint16 bit_flags = 0;
6031 
6032     if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6033         bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6034 
6035     if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6036         bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6037 
6038     if ((int)level_and_flags < 0)
6039         level_and_flags = MZ_DEFAULT_LEVEL;
6040     level = level_and_flags & 0xF;
6041     store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6042 
6043     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6044         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6045 
6046     pState = pZip->m_pState;
6047 
6048     if (pState->m_zip64)
6049     {
6050         if (pZip->m_total_files == MZ_UINT32_MAX)
6051             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6052     }
6053     else
6054     {
6055         if (pZip->m_total_files == MZ_UINT16_MAX)
6056         {
6057             pState->m_zip64 = MZ_TRUE;
6058             /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6059         }
6060         if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6061         {
6062             pState->m_zip64 = MZ_TRUE;
6063             /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6064         }
6065     }
6066 
6067     if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6068         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6069 
6070     if (!mz_zip_writer_validate_archive_name(pArchive_name))
6071         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6072 
6073 #ifndef MINIZ_NO_TIME
6074     if (last_modified != NULL)
6075     {
6076         mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6077     }
6078     else
6079     {
6080         MZ_TIME_T cur_time;
6081         time(&cur_time);
6082         mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6083     }
6084 #endif /* #ifndef MINIZ_NO_TIME */
6085 
6086     archive_name_size = strlen(pArchive_name);
6087     if (archive_name_size > MZ_UINT16_MAX)
6088         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6089 
6090     num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6091 
6092     /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6093     if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6094         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6095 
6096     if (!pState->m_zip64)
6097     {
6098         /* Bail early if the archive would obviously become too large */
6099         if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
6100 			+ MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
6101 			pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
6102 			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
6103         {
6104             pState->m_zip64 = MZ_TRUE;
6105             /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6106         }
6107     }
6108 
6109     if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
6110     {
6111         /* Set DOS Subdirectory attribute bit. */
6112         ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6113 
6114         /* Subdirectories cannot contain data. */
6115         if ((buf_size) || (uncomp_size))
6116             return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6117     }
6118 
6119     /* Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) */
6120     if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + (pState->m_zip64 ? MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE : 0))) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1)))
6121         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6122 
6123     if ((!store_data_uncompressed) && (buf_size))
6124     {
6125         if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6126             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6127     }
6128 
6129     if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6130     {
6131         pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6132         return MZ_FALSE;
6133     }
6134 
6135     local_dir_header_ofs += num_alignment_padding_bytes;
6136     if (pZip->m_file_offset_alignment)
6137     {
6138         MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6139     }
6140     cur_archive_file_ofs += num_alignment_padding_bytes;
6141 
6142     MZ_CLEAR_OBJ(local_dir_header);
6143 
6144     if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6145     {
6146         method = MZ_DEFLATED;
6147     }
6148 
6149     if (pState->m_zip64)
6150     {
6151         if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6152         {
6153             pExtra_data = extra_data;
6154             extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6155                                                                (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6156         }
6157 
6158         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
6159             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6160 
6161         if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6162             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6163 
6164         cur_archive_file_ofs += sizeof(local_dir_header);
6165 
6166         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6167         {
6168             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6169             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6170         }
6171         cur_archive_file_ofs += archive_name_size;
6172 
6173         if (pExtra_data != NULL)
6174         {
6175             if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6176                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6177 
6178             cur_archive_file_ofs += extra_size;
6179         }
6180     }
6181     else
6182     {
6183         if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6184             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6185         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, bit_flags, dos_time, dos_date))
6186             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6187 
6188         if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6189             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6190 
6191         cur_archive_file_ofs += sizeof(local_dir_header);
6192 
6193         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6194         {
6195             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6196             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6197         }
6198         cur_archive_file_ofs += archive_name_size;
6199     }
6200 
6201     if (user_extra_data_len > 0)
6202     {
6203         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6204             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6205 
6206         cur_archive_file_ofs += user_extra_data_len;
6207     }
6208 
6209     if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6210     {
6211         uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6212         uncomp_size = buf_size;
6213         if (uncomp_size <= 3)
6214         {
6215             level = 0;
6216             store_data_uncompressed = MZ_TRUE;
6217         }
6218     }
6219 
6220     if (store_data_uncompressed)
6221     {
6222         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6223         {
6224             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6225             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6226         }
6227 
6228         cur_archive_file_ofs += buf_size;
6229         comp_size = buf_size;
6230     }
6231     else if (buf_size)
6232     {
6233         mz_zip_writer_add_state state;
6234 
6235         state.m_pZip = pZip;
6236         state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6237         state.m_comp_size = 0;
6238 
6239         if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) ||
6240             (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6241         {
6242             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6243             return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6244         }
6245 
6246         comp_size = state.m_comp_size;
6247         cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6248     }
6249 
6250     pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6251     pComp = NULL;
6252 
6253     if (uncomp_size)
6254     {
6255         mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6256         mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6257 
6258         MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
6259 
6260         MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6261         MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6262         if (pExtra_data == NULL)
6263         {
6264             if (comp_size > MZ_UINT32_MAX)
6265                 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6266 
6267             MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6268             MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6269         }
6270         else
6271         {
6272             MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6273             MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6274             local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6275         }
6276 
6277         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6278             return MZ_FALSE;
6279 
6280         cur_archive_file_ofs += local_dir_footer_size;
6281     }
6282 
6283     if (pExtra_data != NULL)
6284     {
6285         extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6286                                                            (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6287     }
6288 
6289     if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment,
6290                                           comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6291                                           user_extra_data_central, user_extra_data_central_len))
6292         return MZ_FALSE;
6293 
6294     pZip->m_total_files++;
6295     pZip->m_archive_size = cur_archive_file_ofs;
6296 
6297     return MZ_TRUE;
6298 }
6299 
6300 #ifndef MINIZ_NO_STDIO
mz_zip_writer_add_cfile(mz_zip_archive * pZip,const char * pArchive_name,MZ_FILE * pSrc_file,mz_uint64 size_to_add,const MZ_TIME_T * pFile_time,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,const char * user_extra_data,mz_uint user_extra_data_len,const char * user_extra_data_central,mz_uint user_extra_data_central_len)6301 mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6302                                 const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6303 {
6304     mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6305     mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6306     mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6307     mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
6308     size_t archive_name_size;
6309     mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6310     mz_uint8 *pExtra_data = NULL;
6311     mz_uint32 extra_size = 0;
6312     mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6313     mz_zip_internal_state *pState;
6314 
6315     if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6316         gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6317 
6318     if ((int)level_and_flags < 0)
6319         level_and_flags = MZ_DEFAULT_LEVEL;
6320     level = level_and_flags & 0xF;
6321 
6322     /* Sanity checks */
6323     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6324         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6325 
6326     pState = pZip->m_pState;
6327 
6328     if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
6329     {
6330         /* Source file is too large for non-zip64 */
6331         /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6332         pState->m_zip64 = MZ_TRUE;
6333     }
6334 
6335     /* We could support this, but why? */
6336     if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6337         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6338 
6339     if (!mz_zip_writer_validate_archive_name(pArchive_name))
6340         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6341 
6342     if (pState->m_zip64)
6343     {
6344         if (pZip->m_total_files == MZ_UINT32_MAX)
6345             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6346     }
6347     else
6348     {
6349         if (pZip->m_total_files == MZ_UINT16_MAX)
6350         {
6351             pState->m_zip64 = MZ_TRUE;
6352             /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6353         }
6354     }
6355 
6356     archive_name_size = strlen(pArchive_name);
6357     if (archive_name_size > MZ_UINT16_MAX)
6358         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6359 
6360     num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6361 
6362     /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6363     if (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE + comment_size) >= MZ_UINT32_MAX)
6364         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6365 
6366     if (!pState->m_zip64)
6367     {
6368         /* Bail early if the archive would obviously become too large */
6369         if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
6370 			+ archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
6371 			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
6372         {
6373             pState->m_zip64 = MZ_TRUE;
6374             /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6375         }
6376     }
6377 
6378 #ifndef MINIZ_NO_TIME
6379     if (pFile_time)
6380     {
6381         mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6382     }
6383 #endif
6384 
6385     if (uncomp_size <= 3)
6386         level = 0;
6387 
6388     if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6389     {
6390         return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6391     }
6392 
6393     cur_archive_file_ofs += num_alignment_padding_bytes;
6394     local_dir_header_ofs = cur_archive_file_ofs;
6395 
6396     if (pZip->m_file_offset_alignment)
6397     {
6398         MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6399     }
6400 
6401     if (uncomp_size && level)
6402     {
6403         method = MZ_DEFLATED;
6404     }
6405 
6406     MZ_CLEAR_OBJ(local_dir_header);
6407     if (pState->m_zip64)
6408     {
6409         if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6410         {
6411             pExtra_data = extra_data;
6412             extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6413                                                                (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6414         }
6415 
6416         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, extra_size + user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6417             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6418 
6419         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6420             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6421 
6422         cur_archive_file_ofs += sizeof(local_dir_header);
6423 
6424         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6425         {
6426             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6427         }
6428 
6429         cur_archive_file_ofs += archive_name_size;
6430 
6431         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6432             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6433 
6434         cur_archive_file_ofs += extra_size;
6435     }
6436     else
6437     {
6438         if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6439             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6440         if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, user_extra_data_len, 0, 0, 0, method, gen_flags, dos_time, dos_date))
6441             return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6442 
6443         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6444             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6445 
6446         cur_archive_file_ofs += sizeof(local_dir_header);
6447 
6448         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6449         {
6450             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6451         }
6452 
6453         cur_archive_file_ofs += archive_name_size;
6454     }
6455 
6456     if (user_extra_data_len > 0)
6457     {
6458         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6459             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6460 
6461         cur_archive_file_ofs += user_extra_data_len;
6462     }
6463 
6464     if (uncomp_size)
6465     {
6466         mz_uint64 uncomp_remaining = uncomp_size;
6467         void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6468         if (!pRead_buf)
6469         {
6470             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6471         }
6472 
6473         if (!level)
6474         {
6475             while (uncomp_remaining)
6476             {
6477                 mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6478                 if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
6479                 {
6480                     pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6481                     return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6482                 }
6483                 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6484                 uncomp_remaining -= n;
6485                 cur_archive_file_ofs += n;
6486             }
6487             comp_size = uncomp_size;
6488         }
6489         else
6490         {
6491             mz_bool result = MZ_FALSE;
6492             mz_zip_writer_add_state state;
6493             tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6494             if (!pComp)
6495             {
6496                 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6497                 return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6498             }
6499 
6500             state.m_pZip = pZip;
6501             state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6502             state.m_comp_size = 0;
6503 
6504             if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY)
6505             {
6506                 pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6507                 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6508                 return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6509             }
6510 
6511             for (;;)
6512             {
6513                 size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6514                 tdefl_status status;
6515                 tdefl_flush flush = TDEFL_NO_FLUSH;
6516 
6517                 if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size)
6518                 {
6519                     mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6520                     break;
6521                 }
6522 
6523                 uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6524                 uncomp_remaining -= in_buf_size;
6525 
6526                 if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6527                     flush = TDEFL_FULL_FLUSH;
6528 
6529                 status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
6530                 if (status == TDEFL_STATUS_DONE)
6531                 {
6532                     result = MZ_TRUE;
6533                     break;
6534                 }
6535                 else if (status != TDEFL_STATUS_OKAY)
6536                 {
6537                     mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6538                     break;
6539                 }
6540             }
6541 
6542             pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6543 
6544             if (!result)
6545             {
6546                 pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6547                 return MZ_FALSE;
6548             }
6549 
6550             comp_size = state.m_comp_size;
6551             cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6552         }
6553 
6554         pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6555     }
6556 
6557     {
6558         mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6559         mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6560 
6561         MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6562         MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6563         if (pExtra_data == NULL)
6564         {
6565             if (comp_size > MZ_UINT32_MAX)
6566                 return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6567 
6568             MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6569             MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6570         }
6571         else
6572         {
6573             MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6574             MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6575             local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6576         }
6577 
6578         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6579             return MZ_FALSE;
6580 
6581         cur_archive_file_ofs += local_dir_footer_size;
6582     }
6583 
6584     if (pExtra_data != NULL)
6585     {
6586         extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6587                                                            (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6588     }
6589 
6590     if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, extra_size, pComment, comment_size,
6591                                           uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6592                                           user_extra_data_central, user_extra_data_central_len))
6593         return MZ_FALSE;
6594 
6595     pZip->m_total_files++;
6596     pZip->m_archive_size = cur_archive_file_ofs;
6597 
6598     return MZ_TRUE;
6599 }
6600 
mz_zip_writer_add_file(mz_zip_archive * pZip,const char * pArchive_name,const char * pSrc_filename,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)6601 mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
6602 {
6603     MZ_FILE *pSrc_file = NULL;
6604     mz_uint64 uncomp_size = 0;
6605     MZ_TIME_T file_modified_time;
6606     MZ_TIME_T *pFile_time = NULL;
6607     mz_bool status;
6608 
6609     memset(&file_modified_time, 0, sizeof(file_modified_time));
6610 
6611 #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6612     pFile_time = &file_modified_time;
6613     if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6614         return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
6615 #endif
6616 
6617     pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6618     if (!pSrc_file)
6619         return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6620 
6621     MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6622     uncomp_size = MZ_FTELL64(pSrc_file);
6623     MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6624 
6625     status = mz_zip_writer_add_cfile(pZip, pArchive_name, pSrc_file, uncomp_size, pFile_time, pComment, comment_size, level_and_flags, NULL, 0, NULL, 0);
6626 
6627     MZ_FCLOSE(pSrc_file);
6628 
6629     return status;
6630 }
6631 #endif /* #ifndef MINIZ_NO_STDIO */
6632 
mz_zip_writer_update_zip64_extension_block(mz_zip_array * pNew_ext,mz_zip_archive * pZip,const mz_uint8 * pExt,uint32_t ext_len,mz_uint64 * pComp_size,mz_uint64 * pUncomp_size,mz_uint64 * pLocal_header_ofs,mz_uint32 * pDisk_start)6633 static mz_bool mz_zip_writer_update_zip64_extension_block(mz_zip_array *pNew_ext, mz_zip_archive *pZip, const mz_uint8 *pExt, uint32_t ext_len, mz_uint64 *pComp_size, mz_uint64 *pUncomp_size, mz_uint64 *pLocal_header_ofs, mz_uint32 *pDisk_start)
6634 {
6635     /* + 64 should be enough for any new zip64 data */
6636     if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6637         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6638 
6639     mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6640 
6641     if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6642     {
6643         mz_uint8 new_ext_block[64];
6644         mz_uint8 *pDst = new_ext_block;
6645         mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6646         mz_write_le16(pDst + sizeof(mz_uint16), 0);
6647         pDst += sizeof(mz_uint16) * 2;
6648 
6649         if (pUncomp_size)
6650         {
6651             mz_write_le64(pDst, *pUncomp_size);
6652             pDst += sizeof(mz_uint64);
6653         }
6654 
6655         if (pComp_size)
6656         {
6657             mz_write_le64(pDst, *pComp_size);
6658             pDst += sizeof(mz_uint64);
6659         }
6660 
6661         if (pLocal_header_ofs)
6662         {
6663             mz_write_le64(pDst, *pLocal_header_ofs);
6664             pDst += sizeof(mz_uint64);
6665         }
6666 
6667         if (pDisk_start)
6668         {
6669             mz_write_le32(pDst, *pDisk_start);
6670             pDst += sizeof(mz_uint32);
6671         }
6672 
6673         mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
6674 
6675         if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6676             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6677     }
6678 
6679     if ((pExt) && (ext_len))
6680     {
6681         mz_uint32 extra_size_remaining = ext_len;
6682         const mz_uint8 *pExtra_data = pExt;
6683 
6684         do
6685         {
6686             mz_uint32 field_id, field_data_size, field_total_size;
6687 
6688             if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6689                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6690 
6691             field_id = MZ_READ_LE16(pExtra_data);
6692             field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6693             field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6694 
6695             if (field_total_size > extra_size_remaining)
6696                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6697 
6698             if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6699             {
6700                 if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6701                     return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6702             }
6703 
6704             pExtra_data += field_total_size;
6705             extra_size_remaining -= field_total_size;
6706         } while (extra_size_remaining);
6707     }
6708 
6709     return MZ_TRUE;
6710 }
6711 
6712 /* TODO: This func is now pretty freakin complex due to zip64, split it up? */
mz_zip_writer_add_from_zip_reader(mz_zip_archive * pZip,mz_zip_archive * pSource_zip,mz_uint src_file_index)6713 mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
6714 {
6715     mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
6716     mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
6717     mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6718     mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
6719     mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6720     mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6721     size_t orig_central_dir_size;
6722     mz_zip_internal_state *pState;
6723     void *pBuf;
6724     const mz_uint8 *pSrc_central_header;
6725     mz_zip_archive_file_stat src_file_stat;
6726     mz_uint32 src_filename_len, src_comment_len, src_ext_len;
6727     mz_uint32 local_header_filename_size, local_header_extra_len;
6728     mz_uint64 local_header_comp_size, local_header_uncomp_size;
6729     mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
6730 
6731     /* Sanity checks */
6732     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
6733         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6734 
6735     pState = pZip->m_pState;
6736 
6737     /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
6738     if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
6739         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6740 
6741     /* Get pointer to the source central dir header and crack it */
6742     if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
6743         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6744 
6745     if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
6746         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6747 
6748     src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
6749     src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
6750     src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
6751     src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
6752 
6753     /* TODO: We don't support central dir's >= MZ_UINT32_MAX bytes right now (+32 fudge factor in case we need to add more extra data) */
6754     if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
6755         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6756 
6757     num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6758 
6759     if (!pState->m_zip64)
6760     {
6761         if (pZip->m_total_files == MZ_UINT16_MAX)
6762             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6763     }
6764     else
6765     {
6766         /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
6767         if (pZip->m_total_files == MZ_UINT32_MAX)
6768             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6769     }
6770 
6771     if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
6772         return MZ_FALSE;
6773 
6774     cur_src_file_ofs = src_file_stat.m_local_header_ofs;
6775     cur_dst_file_ofs = pZip->m_archive_size;
6776 
6777     /* Read the source archive's local dir header */
6778     if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6779         return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6780 
6781     if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
6782         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6783 
6784     cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6785 
6786     /* Compute the total size we need to copy (filename+extra data+compressed data) */
6787     local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
6788     local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
6789     local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
6790     local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
6791     src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
6792 
6793     /* Try to find a zip64 extended information field */
6794     if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
6795     {
6796         mz_zip_array file_data_array;
6797         const mz_uint8 *pExtra_data;
6798         mz_uint32 extra_size_remaining = local_header_extra_len;
6799 
6800         mz_zip_array_init(&file_data_array, 1);
6801         if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
6802         {
6803             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6804         }
6805 
6806         if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, src_file_stat.m_local_header_ofs + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + local_header_filename_size, file_data_array.m_p, local_header_extra_len) != local_header_extra_len)
6807         {
6808             mz_zip_array_clear(pZip, &file_data_array);
6809             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6810         }
6811 
6812         pExtra_data = (const mz_uint8 *)file_data_array.m_p;
6813 
6814         do
6815         {
6816             mz_uint32 field_id, field_data_size, field_total_size;
6817 
6818             if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6819             {
6820                 mz_zip_array_clear(pZip, &file_data_array);
6821                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6822             }
6823 
6824             field_id = MZ_READ_LE16(pExtra_data);
6825             field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6826             field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6827 
6828             if (field_total_size > extra_size_remaining)
6829             {
6830                 mz_zip_array_clear(pZip, &file_data_array);
6831                 return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6832             }
6833 
6834             if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6835             {
6836                 const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
6837 
6838                 if (field_data_size < sizeof(mz_uint64) * 2)
6839                 {
6840                     mz_zip_array_clear(pZip, &file_data_array);
6841                     return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6842                 }
6843 
6844                 local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
6845                 local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
6846 
6847                 found_zip64_ext_data_in_ldir = MZ_TRUE;
6848                 break;
6849             }
6850 
6851             pExtra_data += field_total_size;
6852             extra_size_remaining -= field_total_size;
6853         } while (extra_size_remaining);
6854 
6855         mz_zip_array_clear(pZip, &file_data_array);
6856     }
6857 
6858     if (!pState->m_zip64)
6859     {
6860         /* Try to detect if the new archive will most likely wind up too big and bail early (+(sizeof(mz_uint32) * 4) is for the optional descriptor which could be present, +64 is a fudge factor). */
6861         /* We also check when the archive is finalized so this doesn't need to be perfect. */
6862         mz_uint64 approx_new_archive_size = cur_dst_file_ofs + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + src_archive_bytes_remaining + (sizeof(mz_uint32) * 4) +
6863                                             pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 64;
6864 
6865         if (approx_new_archive_size >= MZ_UINT32_MAX)
6866             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6867     }
6868 
6869     /* Write dest archive padding */
6870     if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
6871         return MZ_FALSE;
6872 
6873     cur_dst_file_ofs += num_alignment_padding_bytes;
6874 
6875     local_dir_header_ofs = cur_dst_file_ofs;
6876     if (pZip->m_file_offset_alignment)
6877     {
6878         MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6879     }
6880 
6881     /* The original zip's local header+ext block doesn't change, even with zip64, so we can just copy it over to the dest zip */
6882     if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE)
6883         return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6884 
6885     cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
6886 
6887     /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
6888     if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(32U, MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining)))))
6889         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6890 
6891     while (src_archive_bytes_remaining)
6892     {
6893         n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
6894         if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
6895         {
6896             pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6897             return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6898         }
6899         cur_src_file_ofs += n;
6900 
6901         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
6902         {
6903             pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6904             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6905         }
6906         cur_dst_file_ofs += n;
6907 
6908         src_archive_bytes_remaining -= n;
6909     }
6910 
6911     /* Now deal with the optional data descriptor */
6912     bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
6913     if (bit_flags & 8)
6914     {
6915         /* Copy data descriptor */
6916         if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
6917         {
6918             /* src is zip64, dest must be zip64 */
6919 
6920             /* name			uint32_t's */
6921             /* id				1 (optional in zip64?) */
6922             /* crc			1 */
6923             /* comp_size	2 */
6924             /* uncomp_size 2 */
6925             if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
6926             {
6927                 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6928                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6929             }
6930 
6931             n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
6932         }
6933         else
6934         {
6935             /* src is NOT zip64 */
6936             mz_bool has_id;
6937 
6938             if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
6939             {
6940                 pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6941                 return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6942             }
6943 
6944             has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
6945 
6946             if (pZip->m_pState->m_zip64)
6947             {
6948                 /* dest is zip64, so upgrade the data descriptor */
6949                 const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));
6950                 const mz_uint32 src_crc32 = pSrc_descriptor[0];
6951                 const mz_uint64 src_comp_size = pSrc_descriptor[1];
6952                 const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
6953 
6954                 mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
6955                 mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
6956                 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
6957                 mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
6958 
6959                 n = sizeof(mz_uint32) * 6;
6960             }
6961             else
6962             {
6963                 /* dest is NOT zip64, just copy it as-is */
6964                 n = sizeof(mz_uint32) * (has_id ? 4 : 3);
6965             }
6966         }
6967 
6968         if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
6969         {
6970             pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6971             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6972         }
6973 
6974         cur_src_file_ofs += n;
6975         cur_dst_file_ofs += n;
6976     }
6977     pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
6978 
6979     /* Finally, add the new central dir header */
6980     orig_central_dir_size = pState->m_central_dir.m_size;
6981 
6982     memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6983 
6984     if (pState->m_zip64)
6985     {
6986         /* This is the painful part: We need to write a new central dir header + ext block with updated zip64 fields, and ensure the old fields (if any) are not included. */
6987         const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
6988         mz_zip_array new_ext_block;
6989 
6990         mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
6991 
6992         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
6993         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
6994         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
6995 
6996         if (!mz_zip_writer_update_zip64_extension_block(&new_ext_block, pZip, pSrc_ext, src_ext_len, &src_file_stat.m_comp_size, &src_file_stat.m_uncomp_size, &local_dir_header_ofs, NULL))
6997         {
6998             mz_zip_array_clear(pZip, &new_ext_block);
6999             return MZ_FALSE;
7000         }
7001 
7002         MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7003 
7004         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7005         {
7006             mz_zip_array_clear(pZip, &new_ext_block);
7007             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7008         }
7009 
7010         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7011         {
7012             mz_zip_array_clear(pZip, &new_ext_block);
7013             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7014             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7015         }
7016 
7017         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7018         {
7019             mz_zip_array_clear(pZip, &new_ext_block);
7020             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7021             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7022         }
7023 
7024         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len + src_ext_len, src_comment_len))
7025         {
7026             mz_zip_array_clear(pZip, &new_ext_block);
7027             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7028             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7029         }
7030 
7031         mz_zip_array_clear(pZip, &new_ext_block);
7032     }
7033     else
7034     {
7035         /* sanity checks */
7036         if (cur_dst_file_ofs > MZ_UINT32_MAX)
7037             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7038 
7039         if (local_dir_header_ofs >= MZ_UINT32_MAX)
7040             return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7041 
7042         MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7043 
7044         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7045             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7046 
7047         if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_central_dir_following_data_size))
7048         {
7049             mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7050             return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7051         }
7052     }
7053 
7054     /* This shouldn't trigger unless we screwed up during the initial sanity checks */
7055     if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7056     {
7057         /* TODO: Support central dirs >= 32-bits in size */
7058         mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7059         return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7060     }
7061 
7062     n = (mz_uint32)orig_central_dir_size;
7063     if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
7064     {
7065         mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7066         return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7067     }
7068 
7069     pZip->m_total_files++;
7070     pZip->m_archive_size = cur_dst_file_ofs;
7071 
7072     return MZ_TRUE;
7073 }
7074 
mz_zip_writer_finalize_archive(mz_zip_archive * pZip)7075 mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
7076 {
7077     mz_zip_internal_state *pState;
7078     mz_uint64 central_dir_ofs, central_dir_size;
7079     mz_uint8 hdr[256];
7080 
7081     if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
7082         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7083 
7084     pState = pZip->m_pState;
7085 
7086     if (pState->m_zip64)
7087     {
7088         if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
7089             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7090     }
7091     else
7092     {
7093         if ((pZip->m_total_files > MZ_UINT16_MAX) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX))
7094             return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7095     }
7096 
7097     central_dir_ofs = 0;
7098     central_dir_size = 0;
7099     if (pZip->m_total_files)
7100     {
7101         /* Write central directory */
7102         central_dir_ofs = pZip->m_archive_size;
7103         central_dir_size = pState->m_central_dir.m_size;
7104         pZip->m_central_directory_file_ofs = central_dir_ofs;
7105         if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size)
7106             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7107 
7108         pZip->m_archive_size += central_dir_size;
7109     }
7110 
7111     if (pState->m_zip64)
7112     {
7113         /* Write zip64 end of central directory header */
7114         mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
7115 
7116         MZ_CLEAR_OBJ(hdr);
7117         MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
7118         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - sizeof(mz_uint32) - sizeof(mz_uint64));
7119         MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
7120         MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
7121         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
7122         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
7123         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
7124         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
7125         if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE)
7126             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7127 
7128         pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
7129 
7130         /* Write zip64 end of central directory locator */
7131         MZ_CLEAR_OBJ(hdr);
7132         MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
7133         MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
7134         MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
7135         if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE) != MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE)
7136             return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7137 
7138         pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
7139     }
7140 
7141     /* Write end of central directory record */
7142     MZ_CLEAR_OBJ(hdr);
7143     MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
7144     MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7145     MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7146     MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));
7147     MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
7148 
7149     if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
7150         return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7151 
7152 #ifndef MINIZ_NO_STDIO
7153     if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
7154         return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7155 #endif /* #ifndef MINIZ_NO_STDIO */
7156 
7157     pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
7158 
7159     pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
7160     return MZ_TRUE;
7161 }
7162 
mz_zip_writer_finalize_heap_archive(mz_zip_archive * pZip,void ** ppBuf,size_t * pSize)7163 mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
7164 {
7165     if ((!ppBuf) || (!pSize))
7166         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7167 
7168     *ppBuf = NULL;
7169     *pSize = 0;
7170 
7171     if ((!pZip) || (!pZip->m_pState))
7172         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7173 
7174     if (pZip->m_pWrite != mz_zip_heap_write_func)
7175         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7176 
7177     if (!mz_zip_writer_finalize_archive(pZip))
7178         return MZ_FALSE;
7179 
7180     *ppBuf = pZip->m_pState->m_pMem;
7181     *pSize = pZip->m_pState->m_mem_size;
7182     pZip->m_pState->m_pMem = NULL;
7183     pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
7184 
7185     return MZ_TRUE;
7186 }
7187 
mz_zip_writer_end(mz_zip_archive * pZip)7188 mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
7189 {
7190     return mz_zip_writer_end_internal(pZip, MZ_TRUE);
7191 }
7192 
7193 #ifndef MINIZ_NO_STDIO
mz_zip_add_mem_to_archive_file_in_place(const char * pZip_filename,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags)7194 mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags)
7195 {
7196     return mz_zip_add_mem_to_archive_file_in_place_v2(pZip_filename, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, NULL);
7197 }
7198 
mz_zip_add_mem_to_archive_file_in_place_v2(const char * pZip_filename,const char * pArchive_name,const void * pBuf,size_t buf_size,const void * pComment,mz_uint16 comment_size,mz_uint level_and_flags,mz_zip_error * pErr)7199 mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr)
7200 {
7201     mz_bool status, created_new_archive = MZ_FALSE;
7202     mz_zip_archive zip_archive;
7203     struct MZ_FILE_STAT_STRUCT file_stat;
7204     mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7205 
7206     mz_zip_zero_struct(&zip_archive);
7207     if ((int)level_and_flags < 0)
7208         level_and_flags = MZ_DEFAULT_LEVEL;
7209 
7210     if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
7211     {
7212         if (pErr)
7213             *pErr = MZ_ZIP_INVALID_PARAMETER;
7214         return MZ_FALSE;
7215     }
7216 
7217     if (!mz_zip_writer_validate_archive_name(pArchive_name))
7218     {
7219         if (pErr)
7220             *pErr = MZ_ZIP_INVALID_FILENAME;
7221         return MZ_FALSE;
7222     }
7223 
7224     /* Important: The regular non-64 bit version of stat() can fail here if the file is very large, which could cause the archive to be overwritten. */
7225     /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
7226     if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
7227     {
7228         /* Create a new archive. */
7229         if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
7230         {
7231             if (pErr)
7232                 *pErr = zip_archive.m_last_error;
7233             return MZ_FALSE;
7234         }
7235 
7236         created_new_archive = MZ_TRUE;
7237     }
7238     else
7239     {
7240         /* Append to an existing archive. */
7241         if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7242         {
7243             if (pErr)
7244                 *pErr = zip_archive.m_last_error;
7245             return MZ_FALSE;
7246         }
7247 
7248         if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
7249         {
7250             if (pErr)
7251                 *pErr = zip_archive.m_last_error;
7252 
7253             mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
7254 
7255             return MZ_FALSE;
7256         }
7257     }
7258 
7259     status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
7260     actual_err = zip_archive.m_last_error;
7261 
7262     /* Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) */
7263     if (!mz_zip_writer_finalize_archive(&zip_archive))
7264     {
7265         if (!actual_err)
7266             actual_err = zip_archive.m_last_error;
7267 
7268         status = MZ_FALSE;
7269     }
7270 
7271     if (!mz_zip_writer_end_internal(&zip_archive, status))
7272     {
7273         if (!actual_err)
7274             actual_err = zip_archive.m_last_error;
7275 
7276         status = MZ_FALSE;
7277     }
7278 
7279     if ((!status) && (created_new_archive))
7280     {
7281         /* It's a new archive and something went wrong, so just delete it. */
7282         int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
7283         (void)ignoredStatus;
7284     }
7285 
7286     if (pErr)
7287         *pErr = actual_err;
7288 
7289     return status;
7290 }
7291 
mz_zip_extract_archive_file_to_heap_v2(const char * pZip_filename,const char * pArchive_name,const char * pComment,size_t * pSize,mz_uint flags,mz_zip_error * pErr)7292 void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr)
7293 {
7294     mz_uint32 file_index;
7295     mz_zip_archive zip_archive;
7296     void *p = NULL;
7297 
7298     if (pSize)
7299         *pSize = 0;
7300 
7301     if ((!pZip_filename) || (!pArchive_name))
7302     {
7303         if (pErr)
7304             *pErr = MZ_ZIP_INVALID_PARAMETER;
7305 
7306         return NULL;
7307     }
7308 
7309     mz_zip_zero_struct(&zip_archive);
7310     if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7311     {
7312         if (pErr)
7313             *pErr = zip_archive.m_last_error;
7314 
7315         return NULL;
7316     }
7317 
7318     if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
7319     {
7320         p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
7321     }
7322 
7323     mz_zip_reader_end_internal(&zip_archive, p != NULL);
7324 
7325     if (pErr)
7326         *pErr = zip_archive.m_last_error;
7327 
7328     return p;
7329 }
7330 
mz_zip_extract_archive_file_to_heap(const char * pZip_filename,const char * pArchive_name,size_t * pSize,mz_uint flags)7331 void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
7332 {
7333     return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7334 }
7335 
7336 #endif /* #ifndef MINIZ_NO_STDIO */
7337 
7338 #endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
7339 
7340 /* ------------------- Misc utils */
7341 
mz_zip_get_mode(mz_zip_archive * pZip)7342 mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
7343 {
7344     return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7345 }
7346 
mz_zip_get_type(mz_zip_archive * pZip)7347 mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
7348 {
7349     return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7350 }
7351 
mz_zip_set_last_error(mz_zip_archive * pZip,mz_zip_error err_num)7352 mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
7353 {
7354     mz_zip_error prev_err;
7355 
7356     if (!pZip)
7357         return MZ_ZIP_INVALID_PARAMETER;
7358 
7359     prev_err = pZip->m_last_error;
7360 
7361     pZip->m_last_error = err_num;
7362     return prev_err;
7363 }
7364 
mz_zip_peek_last_error(mz_zip_archive * pZip)7365 mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
7366 {
7367     if (!pZip)
7368         return MZ_ZIP_INVALID_PARAMETER;
7369 
7370     return pZip->m_last_error;
7371 }
7372 
mz_zip_clear_last_error(mz_zip_archive * pZip)7373 mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
7374 {
7375     return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
7376 }
7377 
mz_zip_get_last_error(mz_zip_archive * pZip)7378 mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
7379 {
7380     mz_zip_error prev_err;
7381 
7382     if (!pZip)
7383         return MZ_ZIP_INVALID_PARAMETER;
7384 
7385     prev_err = pZip->m_last_error;
7386 
7387     pZip->m_last_error = MZ_ZIP_NO_ERROR;
7388     return prev_err;
7389 }
7390 
mz_zip_get_error_string(mz_zip_error mz_err)7391 const char *mz_zip_get_error_string(mz_zip_error mz_err)
7392 {
7393     switch (mz_err)
7394     {
7395         case MZ_ZIP_NO_ERROR:
7396             return "no error";
7397         case MZ_ZIP_UNDEFINED_ERROR:
7398             return "undefined error";
7399         case MZ_ZIP_TOO_MANY_FILES:
7400             return "too many files";
7401         case MZ_ZIP_FILE_TOO_LARGE:
7402             return "file too large";
7403         case MZ_ZIP_UNSUPPORTED_METHOD:
7404             return "unsupported method";
7405         case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
7406             return "unsupported encryption";
7407         case MZ_ZIP_UNSUPPORTED_FEATURE:
7408             return "unsupported feature";
7409         case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
7410             return "failed finding central directory";
7411         case MZ_ZIP_NOT_AN_ARCHIVE:
7412             return "not a ZIP archive";
7413         case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
7414             return "invalid header or archive is corrupted";
7415         case MZ_ZIP_UNSUPPORTED_MULTIDISK:
7416             return "unsupported multidisk archive";
7417         case MZ_ZIP_DECOMPRESSION_FAILED:
7418             return "decompression failed or archive is corrupted";
7419         case MZ_ZIP_COMPRESSION_FAILED:
7420             return "compression failed";
7421         case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
7422             return "unexpected decompressed size";
7423         case MZ_ZIP_CRC_CHECK_FAILED:
7424             return "CRC-32 check failed";
7425         case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
7426             return "unsupported central directory size";
7427         case MZ_ZIP_ALLOC_FAILED:
7428             return "allocation failed";
7429         case MZ_ZIP_FILE_OPEN_FAILED:
7430             return "file open failed";
7431         case MZ_ZIP_FILE_CREATE_FAILED:
7432             return "file create failed";
7433         case MZ_ZIP_FILE_WRITE_FAILED:
7434             return "file write failed";
7435         case MZ_ZIP_FILE_READ_FAILED:
7436             return "file read failed";
7437         case MZ_ZIP_FILE_CLOSE_FAILED:
7438             return "file close failed";
7439         case MZ_ZIP_FILE_SEEK_FAILED:
7440             return "file seek failed";
7441         case MZ_ZIP_FILE_STAT_FAILED:
7442             return "file stat failed";
7443         case MZ_ZIP_INVALID_PARAMETER:
7444             return "invalid parameter";
7445         case MZ_ZIP_INVALID_FILENAME:
7446             return "invalid filename";
7447         case MZ_ZIP_BUF_TOO_SMALL:
7448             return "buffer too small";
7449         case MZ_ZIP_INTERNAL_ERROR:
7450             return "internal error";
7451         case MZ_ZIP_FILE_NOT_FOUND:
7452             return "file not found";
7453         case MZ_ZIP_ARCHIVE_TOO_LARGE:
7454             return "archive is too large";
7455         case MZ_ZIP_VALIDATION_FAILED:
7456             return "validation failed";
7457         case MZ_ZIP_WRITE_CALLBACK_FAILED:
7458             return "write calledback failed";
7459         default:
7460             break;
7461     }
7462 
7463     return "unknown error";
7464 }
7465 
7466 /* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
mz_zip_is_zip64(mz_zip_archive * pZip)7467 mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
7468 {
7469     if ((!pZip) || (!pZip->m_pState))
7470         return MZ_FALSE;
7471 
7472     return pZip->m_pState->m_zip64;
7473 }
7474 
mz_zip_get_central_dir_size(mz_zip_archive * pZip)7475 size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
7476 {
7477     if ((!pZip) || (!pZip->m_pState))
7478         return 0;
7479 
7480     return pZip->m_pState->m_central_dir.m_size;
7481 }
7482 
mz_zip_reader_get_num_files(mz_zip_archive * pZip)7483 mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
7484 {
7485     return pZip ? pZip->m_total_files : 0;
7486 }
7487 
mz_zip_get_archive_size(mz_zip_archive * pZip)7488 mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
7489 {
7490     if (!pZip)
7491         return 0;
7492     return pZip->m_archive_size;
7493 }
7494 
mz_zip_get_archive_file_start_offset(mz_zip_archive * pZip)7495 mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
7496 {
7497     if ((!pZip) || (!pZip->m_pState))
7498         return 0;
7499     return pZip->m_pState->m_file_archive_start_ofs;
7500 }
7501 
mz_zip_get_cfile(mz_zip_archive * pZip)7502 MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
7503 {
7504     if ((!pZip) || (!pZip->m_pState))
7505         return 0;
7506     return pZip->m_pState->m_pFile;
7507 }
7508 
mz_zip_read_archive_data(mz_zip_archive * pZip,mz_uint64 file_ofs,void * pBuf,size_t n)7509 size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
7510 {
7511     if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7512         return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7513 
7514     return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7515 }
7516 
mz_zip_reader_get_filename(mz_zip_archive * pZip,mz_uint file_index,char * pFilename,mz_uint filename_buf_size)7517 mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
7518 {
7519     mz_uint n;
7520     const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7521     if (!p)
7522     {
7523         if (filename_buf_size)
7524             pFilename[0] = '\0';
7525         mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7526         return 0;
7527     }
7528     n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7529     if (filename_buf_size)
7530     {
7531         n = MZ_MIN(n, filename_buf_size - 1);
7532         memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7533         pFilename[n] = '\0';
7534     }
7535     return n + 1;
7536 }
7537 
mz_zip_reader_file_stat(mz_zip_archive * pZip,mz_uint file_index,mz_zip_archive_file_stat * pStat)7538 mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
7539 {
7540     return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7541 }
7542 
mz_zip_end(mz_zip_archive * pZip)7543 mz_bool mz_zip_end(mz_zip_archive *pZip)
7544 {
7545     if (!pZip)
7546         return MZ_FALSE;
7547 
7548     if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7549         return mz_zip_reader_end(pZip);
7550 #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7551     else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
7552         return mz_zip_writer_end(pZip);
7553 #endif
7554 
7555     return MZ_FALSE;
7556 }
7557 
7558 #ifdef __cplusplus
7559 }
7560 #endif
7561 
7562 #endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
7563