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