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