pytorch

Форк
0
7831 строка · 319.4 Кб
1
/**************************************************************************
2
 *
3
 * Copyright 2013-2014 RAD Game Tools and Valve Software
4
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
5
 * All Rights Reserved.
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated documentation files (the "Software"), to deal
9
 * in the Software without restriction, including without limitation the rights
10
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
 * copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
 * THE SOFTWARE.
24
 *
25
 **************************************************************************/
26

27
#include  "miniz.h"
28

29
typedef unsigned char mz_validate_uint16[sizeof(mz_uint16) == 2 ? 1 : -1];
30
typedef unsigned char mz_validate_uint32[sizeof(mz_uint32) == 4 ? 1 : -1];
31
typedef unsigned char mz_validate_uint64[sizeof(mz_uint64) == 8 ? 1 : -1];
32

33
#ifdef __cplusplus
34
extern "C" {
35
#endif
36

37
/* ------------------- zlib-style API's */
38

39
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len)
40
{
41
    // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
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
 */
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

162
void mz_free(void *p)
163
{
164
    MZ_FREE(p);
165
}
166

167
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
}
172
void miniz_def_free_func(void *opaque, void *address)
173
{
174
    (void)opaque, (void)address;
175
    MZ_FREE(address);
176
}
177
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

183
const char *mz_version(void)
184
{
185
    return MZ_VERSION;
186
}
187

188
#ifndef MINIZ_NO_ZLIB_APIS
189

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

195
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy)
196
{
197
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
198
    tdefl_compressor *pComp;
199
    mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy);
200

201
    if (!pStream)
202
        return MZ_STREAM_ERROR;
203
    if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)))
204
        return MZ_PARAM_ERROR;
205

206
    pStream->data_type = 0;
207
    pStream->adler = MZ_ADLER32_INIT;
208
    pStream->msg = NULL;
209
    pStream->reserved = 0;
210
    pStream->total_in = 0;
211
    pStream->total_out = 0;
212
    if (!pStream->zalloc)
213
        pStream->zalloc = miniz_def_alloc_func;
214
    if (!pStream->zfree)
215
        pStream->zfree = miniz_def_free_func;
216

217
    pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor));
218
    if (!pComp)
219
        return MZ_MEM_ERROR;
220

221
    pStream->state = (struct mz_internal_state *)pComp;
222

223
    if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY)
224
    {
225
        mz_deflateEnd(pStream);
226
        return MZ_PARAM_ERROR;
227
    }
228

229
    return MZ_OK;
230
}
231

232
int mz_deflateReset(mz_streamp pStream)
233
{
234
    if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree))
235
        return MZ_STREAM_ERROR;
236
    pStream->total_in = pStream->total_out = 0;
237
    tdefl_init((tdefl_compressor *)pStream->state, NULL, NULL, ((tdefl_compressor *)pStream->state)->m_flags);
238
    return MZ_OK;
239
}
240

241
int mz_deflate(mz_streamp pStream, int flush)
242
{
243
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
244
    size_t in_bytes, out_bytes;
245
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
246
    mz_ulong orig_total_in, orig_total_out;
247
    int mz_status = MZ_OK;
248

249
    if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out))
250
        return MZ_STREAM_ERROR;
251
    if (!pStream->avail_out)
252
        return MZ_BUF_ERROR;
253

254
    if (flush == MZ_PARTIAL_FLUSH)
255
        flush = MZ_SYNC_FLUSH;
256

257
    if (((tdefl_compressor *)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE)
258
        return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR;
259

260
    orig_total_in = pStream->total_in;
261
    orig_total_out = pStream->total_out;
262
    for (;;)
263
    {
264
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
265
        tdefl_status defl_status;
266
        in_bytes = pStream->avail_in;
267
        out_bytes = pStream->avail_out;
268

269
        defl_status = tdefl_compress((tdefl_compressor *)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush);
270
        pStream->next_in += (mz_uint)in_bytes;
271
        pStream->avail_in -= (mz_uint)in_bytes;
272
        pStream->total_in += (mz_uint)in_bytes;
273
        pStream->adler = tdefl_get_adler32((tdefl_compressor *)pStream->state);
274

275
        pStream->next_out += (mz_uint)out_bytes;
276
        pStream->avail_out -= (mz_uint)out_bytes;
277
        pStream->total_out += (mz_uint)out_bytes;
278

279
        if (defl_status < 0)
280
        {
281
            mz_status = MZ_STREAM_ERROR;
282
            break;
283
        }
284
        else if (defl_status == TDEFL_STATUS_DONE)
285
        {
286
            mz_status = MZ_STREAM_END;
287
            break;
288
        }
289
        else if (!pStream->avail_out)
290
            break;
291
        else if ((!pStream->avail_in) && (flush != MZ_FINISH))
292
        {
293
            if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out))
294
                break;
295
            return MZ_BUF_ERROR; /* Can't make forward progress without some input.
296
 */
297
        }
298
    }
299
    return mz_status;
300
}
301

302
int mz_deflateEnd(mz_streamp pStream)
303
{
304
    if (!pStream)
305
        return MZ_STREAM_ERROR;
306
    if (pStream->state)
307
    {
308
        pStream->zfree(pStream->opaque, pStream->state);
309
        pStream->state = NULL;
310
    }
311
    return MZ_OK;
312
}
313

314
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len)
315
{
316
    (void)pStream;
317
    /* 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.) */
318
    return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5);
319
}
320

321
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level)
322
{
323
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
324
    int status;
325
    mz_stream stream;
326
    memset(&stream, 0, sizeof(stream));
327

328
    /* In case mz_ulong is 64-bits (argh I hate longs). */
329
    if ((source_len | *pDest_len) > 0xFFFFFFFFU)
330
        return MZ_PARAM_ERROR;
331

332
    stream.next_in = pSource;
333
    stream.avail_in = (mz_uint32)source_len;
334
    stream.next_out = pDest;
335
    stream.avail_out = (mz_uint32)*pDest_len;
336

337
    status = mz_deflateInit(&stream, level);
338
    if (status != MZ_OK)
339
        return status;
340

341
    status = mz_deflate(&stream, MZ_FINISH);
342
    if (status != MZ_STREAM_END)
343
    {
344
        mz_deflateEnd(&stream);
345
        return (status == MZ_OK) ? MZ_BUF_ERROR : status;
346
    }
347

348
    *pDest_len = stream.total_out;
349
    return mz_deflateEnd(&stream);
350
}
351

352
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
353
{
354
    return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION);
355
}
356

357
mz_ulong mz_compressBound(mz_ulong source_len)
358
{
359
    return mz_deflateBound(NULL, source_len);
360
}
361

362
typedef struct
363
{
364
    tinfl_decompressor m_decomp;
365
    mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed;
366
    int m_window_bits;
367
    mz_uint8 m_dict[TINFL_LZ_DICT_SIZE];
368
    tinfl_status m_last_status;
369
} inflate_state;
370

371
int mz_inflateInit2(mz_streamp pStream, int window_bits)
372
{
373
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
374
    inflate_state *pDecomp;
375
    if (!pStream)
376
        return MZ_STREAM_ERROR;
377
    if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))
378
        return MZ_PARAM_ERROR;
379

380
    pStream->data_type = 0;
381
    pStream->adler = 0;
382
    pStream->msg = NULL;
383
    pStream->total_in = 0;
384
    pStream->total_out = 0;
385
    pStream->reserved = 0;
386
    if (!pStream->zalloc)
387
        pStream->zalloc = miniz_def_alloc_func;
388
    if (!pStream->zfree)
389
        pStream->zfree = miniz_def_free_func;
390

391
    pDecomp = (inflate_state *)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state));
392
    if (!pDecomp)
393
        return MZ_MEM_ERROR;
394

395
    pStream->state = (struct mz_internal_state *)pDecomp;
396

397
    tinfl_init(&pDecomp->m_decomp);
398
    pDecomp->m_dict_ofs = 0;
399
    pDecomp->m_dict_avail = 0;
400
    pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
401
    pDecomp->m_first_call = 1;
402
    pDecomp->m_has_flushed = 0;
403
    pDecomp->m_window_bits = window_bits;
404

405
    return MZ_OK;
406
}
407

408
int mz_inflateInit(mz_streamp pStream)
409
{
410
    return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS);
411
}
412

413
int mz_inflateReset(mz_streamp pStream)
414
{
415
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
416
    inflate_state *pDecomp;
417
    if (!pStream)
418
        return MZ_STREAM_ERROR;
419

420
    pStream->data_type = 0;
421
    pStream->adler = 0;
422
    pStream->msg = NULL;
423
    pStream->total_in = 0;
424
    pStream->total_out = 0;
425
    pStream->reserved = 0;
426

427
    pDecomp = (inflate_state *)pStream->state;
428

429
    tinfl_init(&pDecomp->m_decomp);
430
    pDecomp->m_dict_ofs = 0;
431
    pDecomp->m_dict_avail = 0;
432
    pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT;
433
    pDecomp->m_first_call = 1;
434
    pDecomp->m_has_flushed = 0;
435
    /* pDecomp->m_window_bits = window_bits */;
436

437
    return MZ_OK;
438
}
439

440
int mz_inflate(mz_streamp pStream, int flush)
441
{
442
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
443
    inflate_state *pState;
444
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
445
    mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32;
446
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
447
    size_t in_bytes, out_bytes, orig_avail_in;
448
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
449
    tinfl_status status;
450

451
    if ((!pStream) || (!pStream->state))
452
        return MZ_STREAM_ERROR;
453
    if (flush == MZ_PARTIAL_FLUSH)
454
        flush = MZ_SYNC_FLUSH;
455
    if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH))
456
        return MZ_STREAM_ERROR;
457

458
    pState = (inflate_state *)pStream->state;
459
    if (pState->m_window_bits > 0)
460
        decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER;
461
    orig_avail_in = pStream->avail_in;
462

463
    first_call = pState->m_first_call;
464
    pState->m_first_call = 0;
465
    if (pState->m_last_status < 0)
466
        return MZ_DATA_ERROR;
467

468
    if (pState->m_has_flushed && (flush != MZ_FINISH))
469
        return MZ_STREAM_ERROR;
470
    pState->m_has_flushed |= (flush == MZ_FINISH);
471

472
    if ((flush == MZ_FINISH) && (first_call))
473
    {
474
        /* MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. */
475
        decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF;
476
        in_bytes = pStream->avail_in;
477
        out_bytes = pStream->avail_out;
478
        status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags);
479
        pState->m_last_status = status;
480
        pStream->next_in += (mz_uint)in_bytes;
481
        pStream->avail_in -= (mz_uint)in_bytes;
482
        pStream->total_in += (mz_uint)in_bytes;
483
        pStream->adler = tinfl_get_adler32(&pState->m_decomp);
484
        pStream->next_out += (mz_uint)out_bytes;
485
        pStream->avail_out -= (mz_uint)out_bytes;
486
        pStream->total_out += (mz_uint)out_bytes;
487

488
        if (status < 0)
489
            return MZ_DATA_ERROR;
490
        else if (status != TINFL_STATUS_DONE)
491
        {
492
            pState->m_last_status = TINFL_STATUS_FAILED;
493
            return MZ_BUF_ERROR;
494
        }
495
        return MZ_STREAM_END;
496
    }
497
    /* flush != MZ_FINISH then we must assume there's more input. */
498
    if (flush != MZ_FINISH)
499
        decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT;
500

501
    if (pState->m_dict_avail)
502
    {
503
        n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
504
        memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
505
        pStream->next_out += n;
506
        pStream->avail_out -= n;
507
        pStream->total_out += n;
508
        pState->m_dict_avail -= n;
509
        pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
510
        return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
511
    }
512

513
    for (;;)
514
    {
515
        in_bytes = pStream->avail_in;
516
        out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs;
517

518
        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);
519
        pState->m_last_status = status;
520

521
        pStream->next_in += (mz_uint)in_bytes;
522
        pStream->avail_in -= (mz_uint)in_bytes;
523
        pStream->total_in += (mz_uint)in_bytes;
524
        pStream->adler = tinfl_get_adler32(&pState->m_decomp);
525

526
        pState->m_dict_avail = (mz_uint)out_bytes;
527

528
        n = MZ_MIN(pState->m_dict_avail, pStream->avail_out);
529
        memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n);
530
        pStream->next_out += n;
531
        pStream->avail_out -= n;
532
        pStream->total_out += n;
533
        pState->m_dict_avail -= n;
534
        pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1);
535

536
        if (status < 0)
537
            return MZ_DATA_ERROR; /* Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). */
538
        else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
539
            return MZ_BUF_ERROR; /* Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. */
540
        else if (flush == MZ_FINISH)
541
        {
542
            /* The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. */
543
            if (status == TINFL_STATUS_DONE)
544
                return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END;
545
            /* 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. */
546
            else if (!pStream->avail_out)
547
                return MZ_BUF_ERROR;
548
        }
549
        else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail))
550
            break;
551
    }
552

553
    return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK;
554
}
555

556
int mz_inflateEnd(mz_streamp pStream)
557
{
558
    if (!pStream)
559
        return MZ_STREAM_ERROR;
560
    if (pStream->state)
561
    {
562
        pStream->zfree(pStream->opaque, pStream->state);
563
        pStream->state = NULL;
564
    }
565
    return MZ_OK;
566
}
567

568
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
569
{
570
    mz_stream stream;
571
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
572
    int status;
573
    memset(&stream, 0, sizeof(stream));
574

575
    /* In case mz_ulong is 64-bits (argh I hate longs). */
576
    if ((source_len | *pDest_len) > 0xFFFFFFFFU)
577
        return MZ_PARAM_ERROR;
578

579
    stream.next_in = pSource;
580
    stream.avail_in = (mz_uint32)source_len;
581
    stream.next_out = pDest;
582
    stream.avail_out = (mz_uint32)*pDest_len;
583

584
    status = mz_inflateInit(&stream);
585
    if (status != MZ_OK)
586
        return status;
587

588
    status = mz_inflate(&stream, MZ_FINISH);
589
    if (status != MZ_STREAM_END)
590
    {
591
        mz_inflateEnd(&stream);
592
        return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status;
593
    }
594
    *pDest_len = stream.total_out;
595

596
    return mz_inflateEnd(&stream);
597
}
598

599
const char *mz_error(int err)
600
{
601
    static struct
602
    {
603
        int m_err;
604
        const char *m_pDesc;
605
    } s_error_descs[] =
606
        {
607
          { 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" }
608
        };
609
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
610
    mz_uint i;
611
    for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
612
        if (s_error_descs[i].m_err == err)
613
            return s_error_descs[i].m_pDesc;
614
    return NULL;
615
}
616

617
#endif /*MINIZ_NO_ZLIB_APIS */
618

619
#ifdef __cplusplus
620
}
621
#endif
622

623
/*
624
  This is free and unencumbered software released into the public domain.
625

626
  Anyone is free to copy, modify, publish, use, compile, sell, or
627
  distribute this software, either in source code form or as a compiled
628
  binary, for any purpose, commercial or non-commercial, and by any
629
  means.
630

631
  In jurisdictions that recognize copyright laws, the author or authors
632
  of this software dedicate any and all copyright interest in the
633
  software to the public domain. We make this dedication for the benefit
634
  of the public at large and to the detriment of our heirs and
635
  successors. We intend this dedication to be an overt act of
636
  relinquishment in perpetuity of all present and future rights to this
637
  software under copyright law.
638

639
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
640
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
641
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
642
  IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
643
  OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
644
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
645
  OTHER DEALINGS IN THE SOFTWARE.
646

647
  For more information, please refer to <http://unlicense.org/>
648
*/
649
/**************************************************************************
650
 *
651
 * Copyright 2013-2014 RAD Game Tools and Valve Software
652
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
653
 * All Rights Reserved.
654
 *
655
 * Permission is hereby granted, free of charge, to any person obtaining a copy
656
 * of this software and associated documentation files (the "Software"), to deal
657
 * in the Software without restriction, including without limitation the rights
658
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
659
 * copies of the Software, and to permit persons to whom the Software is
660
 * furnished to do so, subject to the following conditions:
661
 *
662
 * The above copyright notice and this permission notice shall be included in
663
 * all copies or substantial portions of the Software.
664
 *
665
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
666
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
667
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
668
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
669
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
670
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
671
 * THE SOFTWARE.
672
 *
673
 **************************************************************************/
674

675

676

677

678
#ifdef __cplusplus
679
extern "C" {
680
#endif
681

682
/* ------------------- Low-level Compression (independent from all decompression API's) */
683

684
/* Purposely making these tables static for faster init and thread safety. */
685
static const mz_uint16 s_tdefl_len_sym[256] =
686
    {
687
      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,
688
      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,
689
      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,
690
      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,
691
      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,
692
      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,
693
      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,
694
      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
695
    };
696

697
static const mz_uint8 s_tdefl_len_extra[256] =
698
    {
699
      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,
700
      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,
701
      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
702
      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 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
703
    };
704

705
static const mz_uint8 s_tdefl_small_dist_sym[512] =
706
    {
707
      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,
708
      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,
709
      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,
710
      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,
711
      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,
712
      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,
713
      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,
714
      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,
715
      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,
716
      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,
717
      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,
718
      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
719
    };
720

721
static const mz_uint8 s_tdefl_small_dist_extra[512] =
722
    {
723
      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,
724
      5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 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,
725
      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,
726
      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,
727
      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
728
      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
729
      7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
730
      7, 7, 7, 7, 7, 7, 7, 7
731
    };
732

733
static const mz_uint8 s_tdefl_large_dist_sym[128] =
734
    {
735
      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,
736
      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,
737
      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
738
    };
739

740
static const mz_uint8 s_tdefl_large_dist_extra[128] =
741
    {
742
      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,
743
      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,
744
      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
745
    };
746

747
/* Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. */
748
typedef struct
749
{
750
    mz_uint16 m_key, m_sym_index;
751
} tdefl_sym_freq;
752
static tdefl_sym_freq *tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq *pSyms0, tdefl_sym_freq *pSyms1)
753
{
754
    // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
755
    mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2];
756
    tdefl_sym_freq *pCur_syms = pSyms0, *pNew_syms = pSyms1;
757
    MZ_CLEAR_OBJ(hist);
758
    for (i = 0; i < num_syms; i++)
759
    {
760
        mz_uint freq = pSyms0[i].m_key;
761
        hist[freq & 0xFF]++;
762
        hist[256 + ((freq >> 8) & 0xFF)]++;
763
    }
764
    while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256]))
765
        total_passes--;
766
    for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8)
767
    {
768
        const mz_uint32 *pHist = &hist[pass << 8];
769
        mz_uint offsets[256], cur_ofs = 0;
770
        for (i = 0; i < 256; i++)
771
        {
772
            offsets[i] = cur_ofs;
773
            cur_ofs += pHist[i];
774
        }
775
        for (i = 0; i < num_syms; i++)
776
            pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i];
777
        {
778
            tdefl_sym_freq *t = pCur_syms;
779
            pCur_syms = pNew_syms;
780
            pNew_syms = t;
781
        }
782
    }
783
    return pCur_syms;
784
}
785

786
/* tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. */
787
static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n)
788
{
789
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
790
    int root, leaf, next, avbl, used, dpth;
791
    if (n == 0)
792
        return;
793
    else if (n == 1)
794
    {
795
        A[0].m_key = 1;
796
        return;
797
    }
798
    A[0].m_key += A[1].m_key;
799
    root = 0;
800
    leaf = 2;
801
    for (next = 1; next < n - 1; next++)
802
    {
803
        if (leaf >= n || A[root].m_key < A[leaf].m_key)
804
        {
805
            A[next].m_key = A[root].m_key;
806
            A[root++].m_key = (mz_uint16)next;
807
        }
808
        else
809
            A[next].m_key = A[leaf++].m_key;
810
        if (leaf >= n || (root < next && A[root].m_key < A[leaf].m_key))
811
        {
812
            A[next].m_key = (mz_uint16)(A[next].m_key + A[root].m_key);
813
            A[root++].m_key = (mz_uint16)next;
814
        }
815
        else
816
            A[next].m_key = (mz_uint16)(A[next].m_key + A[leaf++].m_key);
817
    }
818
    A[n - 2].m_key = 0;
819
    for (next = n - 3; next >= 0; next--)
820
        A[next].m_key = A[A[next].m_key].m_key + 1;
821
    avbl = 1;
822
    used = dpth = 0;
823
    root = n - 2;
824
    next = n - 1;
825
    while (avbl > 0)
826
    {
827
        while (root >= 0 && (int)A[root].m_key == dpth)
828
        {
829
            used++;
830
            root--;
831
        }
832
        while (avbl > used)
833
        {
834
            A[next--].m_key = (mz_uint16)(dpth);
835
            avbl--;
836
        }
837
        avbl = 2 * used;
838
        dpth++;
839
        used = 0;
840
    }
841
}
842

843
/* Limits canonical Huffman code table's max code size. */
844
enum
845
{
846
    TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32
847
};
848
static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size)
849
{
850
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
851
    int i;
852
    mz_uint32 total = 0;
853
    if (code_list_len <= 1)
854
        return;
855
    for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++)
856
        pNum_codes[max_code_size] += pNum_codes[i];
857
    for (i = max_code_size; i > 0; i--)
858
        total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i));
859
    while (total != (1UL << max_code_size))
860
    {
861
        pNum_codes[max_code_size]--;
862
        for (i = max_code_size - 1; i > 0; i--)
863
            if (pNum_codes[i])
864
            {
865
                pNum_codes[i]--;
866
                pNum_codes[i + 1] += 2;
867
                break;
868
            }
869
        total--;
870
    }
871
}
872

873
static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table)
874
{
875
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
876
    int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE];
877
    mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1];
878
    MZ_CLEAR_OBJ(num_codes);
879
    if (static_table)
880
    {
881
        for (i = 0; i < table_len; i++)
882
            num_codes[d->m_huff_code_sizes[table_num][i]]++;
883
    }
884
    else
885
    {
886
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
887
        tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms;
888
        int num_used_syms = 0;
889
        const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0];
890
        for (i = 0; i < table_len; i++)
891
            if (pSym_count[i])
892
            {
893
                syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i];
894
                syms0[num_used_syms++].m_sym_index = (mz_uint16)i;
895
            }
896

897
        pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1);
898
        tdefl_calculate_minimum_redundancy(pSyms, num_used_syms);
899

900
        for (i = 0; i < num_used_syms; i++)
901
            num_codes[pSyms[i].m_key]++;
902

903
        tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit);
904

905
        MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]);
906
        MZ_CLEAR_OBJ(d->m_huff_codes[table_num]);
907
        for (i = 1, j = num_used_syms; i <= code_size_limit; i++)
908
            for (l = num_codes[i]; l > 0; l--)
909
                d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i);
910
    }
911

912
    next_code[1] = 0;
913
    for (j = 0, i = 2; i <= code_size_limit; i++)
914
        next_code[i] = j = ((j + num_codes[i - 1]) << 1);
915

916
    for (i = 0; i < table_len; i++)
917
    {
918
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
919
        mz_uint rev_code = 0, code, code_size;
920
        if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0)
921
            continue;
922
        code = next_code[code_size]++;
923
        for (l = code_size; l > 0; l--, code >>= 1)
924
            rev_code = (rev_code << 1) | (code & 1);
925
        d->m_huff_codes[table_num][i] = (mz_uint16)rev_code;
926
    }
927
}
928

929
#define TDEFL_PUT_BITS(b, l)                                       \
930
    do                                                             \
931
    {                                                              \
932
        mz_uint bits = b;                                          \
933
        mz_uint len = l;                                           \
934
        MZ_ASSERT(bits <= ((1U << len) - 1U));                     \
935
        d->m_bit_buffer |= (bits << d->m_bits_in);                 \
936
        d->m_bits_in += len;                                       \
937
        while (d->m_bits_in >= 8)                                  \
938
        {                                                          \
939
            if (d->m_pOutput_buf < d->m_pOutput_buf_end)           \
940
                *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \
941
            d->m_bit_buffer >>= 8;                                 \
942
            d->m_bits_in -= 8;                                     \
943
        }                                                          \
944
    }                                                              \
945
    MZ_MACRO_END
946

947
#define TDEFL_RLE_PREV_CODE_SIZE()                                                                                       \
948
    {                                                                                                                    \
949
        if (rle_repeat_count)                                                                                            \
950
        {                                                                                                                \
951
            if (rle_repeat_count < 3)                                                                                    \
952
            {                                                                                                            \
953
                d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \
954
                while (rle_repeat_count--)                                                                               \
955
                    packed_code_sizes[num_packed_code_sizes++] = prev_code_size;                                         \
956
            }                                                                                                            \
957
            else                                                                                                         \
958
            {                                                                                                            \
959
                d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1);                                        \
960
                packed_code_sizes[num_packed_code_sizes++] = 16;                                                         \
961
                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3);                           \
962
            }                                                                                                            \
963
            rle_repeat_count = 0;                                                                                        \
964
        }                                                                                                                \
965
    }
966

967
#define TDEFL_RLE_ZERO_CODE_SIZE()                                                         \
968
    {                                                                                      \
969
        if (rle_z_count)                                                                   \
970
        {                                                                                  \
971
            if (rle_z_count < 3)                                                           \
972
            {                                                                              \
973
                d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count);  \
974
                while (rle_z_count--)                                                      \
975
                    packed_code_sizes[num_packed_code_sizes++] = 0;                        \
976
            }                                                                              \
977
            else if (rle_z_count <= 10)                                                    \
978
            {                                                                              \
979
                d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1);          \
980
                packed_code_sizes[num_packed_code_sizes++] = 17;                           \
981
                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3);  \
982
            }                                                                              \
983
            else                                                                           \
984
            {                                                                              \
985
                d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1);          \
986
                packed_code_sizes[num_packed_code_sizes++] = 18;                           \
987
                packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \
988
            }                                                                              \
989
            rle_z_count = 0;                                                               \
990
        }                                                                                  \
991
    }
992

993
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables,cppcoreguidelines-avoid-magic-numbers)
994
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 };
995

996
static void tdefl_start_dynamic_block(tdefl_compressor *d)
997
{
998
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
999
    int num_lit_codes, num_dist_codes, num_bit_lengths;
1000
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1001
    mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index;
1002
    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;
1003

1004
    d->m_huff_count[0][256] = 1;
1005

1006
    tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE);
1007
    tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE);
1008

1009
    for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--)
1010
        if (d->m_huff_code_sizes[0][num_lit_codes - 1])
1011
            break;
1012
    for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--)
1013
        if (d->m_huff_code_sizes[1][num_dist_codes - 1])
1014
            break;
1015

1016
    memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes);
1017
    memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes);
1018
    total_code_sizes_to_pack = num_lit_codes + num_dist_codes;
1019
    num_packed_code_sizes = 0;
1020
    rle_z_count = 0;
1021
    rle_repeat_count = 0;
1022

1023
    memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2);
1024
    for (i = 0; i < total_code_sizes_to_pack; i++)
1025
    {
1026
        mz_uint8 code_size = code_sizes_to_pack[i];
1027
        if (!code_size)
1028
        {
1029
            TDEFL_RLE_PREV_CODE_SIZE();
1030
            if (++rle_z_count == 138)
1031
            {
1032
                TDEFL_RLE_ZERO_CODE_SIZE();
1033
            }
1034
        }
1035
        else
1036
        {
1037
            TDEFL_RLE_ZERO_CODE_SIZE();
1038
            if (code_size != prev_code_size)
1039
            {
1040
                TDEFL_RLE_PREV_CODE_SIZE();
1041
                d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1);
1042
                packed_code_sizes[num_packed_code_sizes++] = code_size;
1043
            }
1044
            else if (++rle_repeat_count == 6)
1045
            {
1046
                TDEFL_RLE_PREV_CODE_SIZE();
1047
            }
1048
        }
1049
        prev_code_size = code_size;
1050
    }
1051
    if (rle_repeat_count)
1052
    {
1053
        TDEFL_RLE_PREV_CODE_SIZE();
1054
    }
1055
    else
1056
    {
1057
        TDEFL_RLE_ZERO_CODE_SIZE();
1058
    }
1059

1060
    tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE);
1061

1062
    TDEFL_PUT_BITS(2, 2);
1063

1064
    TDEFL_PUT_BITS(num_lit_codes - 257, 5);
1065
    TDEFL_PUT_BITS(num_dist_codes - 1, 5);
1066

1067
    for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--)
1068
        if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]])
1069
            break;
1070
    num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1));
1071
    TDEFL_PUT_BITS(num_bit_lengths - 4, 4);
1072
    for (i = 0; (int)i < num_bit_lengths; i++)
1073
        TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3);
1074

1075
    for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;)
1076
    {
1077
        mz_uint code = packed_code_sizes[packed_code_sizes_index++];
1078
        MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2);
1079
        TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]);
1080
        if (code >= 16)
1081
            // NOLINTNEXTLINE(bugprone-signed-char-misuse)
1082
            TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]);
1083
    }
1084
}
1085

1086
static void tdefl_start_static_block(tdefl_compressor *d)
1087
{
1088
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1089
    mz_uint i;
1090
    mz_uint8 *p = &d->m_huff_code_sizes[0][0];
1091

1092
    for (i = 0; i <= 143; ++i)
1093
        *p++ = 8;
1094
    for (; i <= 255; ++i)
1095
        *p++ = 9;
1096
    for (; i <= 279; ++i)
1097
        *p++ = 7;
1098
    for (; i <= 287; ++i)
1099
        *p++ = 8;
1100

1101
    memset(d->m_huff_code_sizes[1], 5, 32);
1102

1103
    tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE);
1104
    tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE);
1105

1106
    TDEFL_PUT_BITS(1, 2);
1107
}
1108

1109
static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
1110

1111
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS
1112
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1113
{
1114
    mz_uint flags;
1115
    mz_uint8 *pLZ_codes;
1116
    mz_uint8 *pOutput_buf = d->m_pOutput_buf;
1117
    mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf;
1118
    mz_uint64 bit_buffer = d->m_bit_buffer;
1119
    mz_uint bits_in = d->m_bits_in;
1120

1121
#define TDEFL_PUT_BITS_FAST(b, l)                    \
1122
    {                                                \
1123
        bit_buffer |= (((mz_uint64)(b)) << bits_in); \
1124
        bits_in += (l);                              \
1125
    }
1126

1127
    flags = 1;
1128
    for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1)
1129
    {
1130
        if (flags == 1)
1131
            flags = *pLZ_codes++ | 0x100;
1132

1133
        if (flags & 1)
1134
        {
1135
            mz_uint s0, s1, n0, n1, sym, num_extra_bits;
1136
            mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1);
1137
            pLZ_codes += 3;
1138

1139
            MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1140
            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]]);
1141
            TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1142

1143
            /* This sequence coaxes MSVC into using cmov's vs. jmp's. */
1144
            s0 = s_tdefl_small_dist_sym[match_dist & 511];
1145
            n0 = s_tdefl_small_dist_extra[match_dist & 511];
1146
            s1 = s_tdefl_large_dist_sym[match_dist >> 8];
1147
            n1 = s_tdefl_large_dist_extra[match_dist >> 8];
1148
            sym = (match_dist < 512) ? s0 : s1;
1149
            num_extra_bits = (match_dist < 512) ? n0 : n1;
1150

1151
            MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1152
            TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1153
            TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1154
        }
1155
        else
1156
        {
1157
            mz_uint lit = *pLZ_codes++;
1158
            MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1159
            TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1160

1161
            if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1162
            {
1163
                flags >>= 1;
1164
                lit = *pLZ_codes++;
1165
                MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1166
                TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1167

1168
                if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end))
1169
                {
1170
                    flags >>= 1;
1171
                    lit = *pLZ_codes++;
1172
                    MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1173
                    TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1174
                }
1175
            }
1176
        }
1177

1178
        if (pOutput_buf >= d->m_pOutput_buf_end)
1179
            return MZ_FALSE;
1180

1181
        *(mz_uint64 *)pOutput_buf = bit_buffer;
1182
        pOutput_buf += (bits_in >> 3);
1183
        bit_buffer >>= (bits_in & ~7);
1184
        bits_in &= 7;
1185
    }
1186

1187
#undef TDEFL_PUT_BITS_FAST
1188

1189
    d->m_pOutput_buf = pOutput_buf;
1190
    d->m_bits_in = 0;
1191
    d->m_bit_buffer = 0;
1192

1193
    while (bits_in)
1194
    {
1195
        mz_uint32 n = MZ_MIN(bits_in, 16);
1196
        TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n);
1197
        bit_buffer >>= n;
1198
        bits_in -= n;
1199
    }
1200

1201
    TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1202

1203
    return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1204
}
1205
#else
1206
static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d)
1207
{
1208
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1209
    mz_uint flags;
1210
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1211
    mz_uint8 *pLZ_codes;
1212

1213
    flags = 1;
1214
    for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1)
1215
    {
1216
        if (flags == 1)
1217
            flags = *pLZ_codes++ | 0x100;
1218
        if (flags & 1)
1219
        {
1220
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1221
            mz_uint sym, num_extra_bits;
1222
            mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8));
1223
            pLZ_codes += 3;
1224

1225
            MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]);
1226
            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]]);
1227
            TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]);
1228

1229
            if (match_dist < 512)
1230
            {
1231
                sym = s_tdefl_small_dist_sym[match_dist];
1232
                num_extra_bits = s_tdefl_small_dist_extra[match_dist];
1233
            }
1234
            else
1235
            {
1236
                sym = s_tdefl_large_dist_sym[match_dist >> 8];
1237
                num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8];
1238
            }
1239
            MZ_ASSERT(d->m_huff_code_sizes[1][sym]);
1240
            TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]);
1241
            TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits);
1242
        }
1243
        else
1244
        {
1245
            mz_uint lit = *pLZ_codes++;
1246
            MZ_ASSERT(d->m_huff_code_sizes[0][lit]);
1247
            TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]);
1248
        }
1249
    }
1250

1251
    TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]);
1252

1253
    return (d->m_pOutput_buf < d->m_pOutput_buf_end);
1254
}
1255
#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS */
1256

1257
static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block)
1258
{
1259
    if (static_block)
1260
        tdefl_start_static_block(d);
1261
    else
1262
        tdefl_start_dynamic_block(d);
1263
    return tdefl_compress_lz_codes(d);
1264
}
1265

1266
static int tdefl_flush_block(tdefl_compressor *d, int flush)
1267
{
1268
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1269
    mz_uint saved_bit_buf, saved_bits_in;
1270
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1271
    mz_uint8 *pSaved_output_buf;
1272
    mz_bool comp_block_succeeded = MZ_FALSE;
1273
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1274
    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;
1275
    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;
1276

1277
    d->m_pOutput_buf = pOutput_buf_start;
1278
    d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16;
1279

1280
    MZ_ASSERT(!d->m_output_flush_remaining);
1281
    d->m_output_flush_ofs = 0;
1282
    d->m_output_flush_remaining = 0;
1283

1284
    *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left);
1285
    d->m_pLZ_code_buf -= (d->m_num_flags_left == 8);
1286

1287
    if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index))
1288
    {
1289
        TDEFL_PUT_BITS(0x78, 8);
1290
        TDEFL_PUT_BITS(0x01, 8);
1291
    }
1292

1293
    TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1);
1294

1295
    pSaved_output_buf = d->m_pOutput_buf;
1296
    saved_bit_buf = d->m_bit_buffer;
1297
    saved_bits_in = d->m_bits_in;
1298

1299
    if (!use_raw_block)
1300
        comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48));
1301

1302
    /* If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. */
1303
    if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) &&
1304
        ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size))
1305
    {
1306
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1307
        mz_uint i;
1308
        d->m_pOutput_buf = pSaved_output_buf;
1309
        d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1310
        TDEFL_PUT_BITS(0, 2);
1311
        if (d->m_bits_in)
1312
        {
1313
            TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1314
        }
1315
        for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF)
1316
        {
1317
            TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16);
1318
        }
1319
        for (i = 0; i < d->m_total_lz_bytes; ++i)
1320
        {
1321
            TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8);
1322
        }
1323
    }
1324
    /* Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. */
1325
    else if (!comp_block_succeeded)
1326
    {
1327
        d->m_pOutput_buf = pSaved_output_buf;
1328
        d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in;
1329
        tdefl_compress_block(d, MZ_TRUE);
1330
    }
1331

1332
    if (flush)
1333
    {
1334
        if (flush == TDEFL_FINISH)
1335
        {
1336
            if (d->m_bits_in)
1337
            {
1338
                TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1339
            }
1340
            if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER)
1341
            {
1342
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1343
                mz_uint i, a = d->m_adler32;
1344
                for (i = 0; i < 4; i++)
1345
                {
1346
                    TDEFL_PUT_BITS((a >> 24) & 0xFF, 8);
1347
                    a <<= 8;
1348
                }
1349
            }
1350
        }
1351
        else
1352
        {
1353
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1354
            mz_uint i, z = 0;
1355
            TDEFL_PUT_BITS(0, 3);
1356
            if (d->m_bits_in)
1357
            {
1358
                TDEFL_PUT_BITS(0, 8 - d->m_bits_in);
1359
            }
1360
            for (i = 2; i; --i, z ^= 0xFFFF)
1361
            {
1362
                TDEFL_PUT_BITS(z & 0xFFFF, 16);
1363
            }
1364
        }
1365
    }
1366

1367
    MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end);
1368

1369
    memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
1370
    memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
1371

1372
    d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
1373
    d->m_pLZ_flags = d->m_lz_code_buf;
1374
    d->m_num_flags_left = 8;
1375
    d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes;
1376
    d->m_total_lz_bytes = 0;
1377
    d->m_block_index++;
1378

1379
    if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0)
1380
    {
1381
        if (d->m_pPut_buf_func)
1382
        {
1383
            *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1384
            if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user))
1385
                return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED);
1386
        }
1387
        else if (pOutput_buf_start == d->m_output_buf)
1388
        {
1389
            int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs));
1390
            memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy);
1391
            d->m_out_buf_ofs += bytes_to_copy;
1392
            if ((n -= bytes_to_copy) != 0)
1393
            {
1394
                d->m_output_flush_ofs = bytes_to_copy;
1395
                d->m_output_flush_remaining = n;
1396
            }
1397
        }
1398
        else
1399
        {
1400
            d->m_out_buf_ofs += n;
1401
        }
1402
    }
1403

1404
    return d->m_output_flush_remaining;
1405
}
1406

1407
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
1408
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
1409
static mz_uint16 TDEFL_READ_UNALIGNED_WORD(const mz_uint8* p)
1410
{
1411
	mz_uint16 ret;
1412
	memcpy(&ret, p, sizeof(mz_uint16));
1413
	return ret;
1414
}
1415
static mz_uint16 TDEFL_READ_UNALIGNED_WORD2(const mz_uint16* p)
1416
{
1417
	mz_uint16 ret;
1418
	memcpy(&ret, p, sizeof(mz_uint16));
1419
	return ret;
1420
}
1421
#else
1422
#define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16 *)(p)
1423
#define TDEFL_READ_UNALIGNED_WORD2(p) *(const mz_uint16 *)(p)
1424
#endif
1425
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)
1426
{
1427
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1428
    mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1429
    mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1430
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1431
    const mz_uint16 *s = (const mz_uint16 *)(d->m_dict + pos), *p, *q;
1432
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1433
    mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD2(s);
1434
    MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1435
    if (max_match_len <= match_len)
1436
        return;
1437
    for (;;)
1438
    {
1439
        for (;;)
1440
        {
1441
            if (--num_probes_left == 0)
1442
                return;
1443
#define TDEFL_PROBE                                                                             \
1444
    next_probe_pos = d->m_next[probe_pos];                                                      \
1445
    if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) \
1446
        return;                                                                                 \
1447
    probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                       \
1448
    if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01)                \
1449
        break;
1450
            TDEFL_PROBE;
1451
            TDEFL_PROBE;
1452
            TDEFL_PROBE;
1453
        }
1454
        if (!dist)
1455
            break;
1456
        q = (const mz_uint16 *)(d->m_dict + probe_pos);
1457
        if (TDEFL_READ_UNALIGNED_WORD2(q) != s01)
1458
            continue;
1459
        p = s;
1460
        probe_len = 32;
1461
        do
1462
        {
1463
        } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1464
                 (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1465
        if (!probe_len)
1466
        {
1467
            *pMatch_dist = dist;
1468
            *pMatch_len = MZ_MIN(max_match_len, (mz_uint)TDEFL_MAX_MATCH_LEN);
1469
            break;
1470
        }
1471
        else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q)) > match_len)
1472
        {
1473
            *pMatch_dist = dist;
1474
            if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len)
1475
                break;
1476
            c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]);
1477
        }
1478
    }
1479
}
1480
#else
1481
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)
1482
{
1483
    mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len;
1484
    mz_uint num_probes_left = d->m_max_probes[match_len >= 32];
1485
    const mz_uint8 *s = d->m_dict + pos, *p, *q;
1486
    mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1];
1487
    MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN);
1488
    if (max_match_len <= match_len)
1489
        return;
1490
    for (;;)
1491
    {
1492
        for (;;)
1493
        {
1494
            if (--num_probes_left == 0)
1495
                return;
1496
#define TDEFL_PROBE                                                                               \
1497
    next_probe_pos = d->m_next[probe_pos];                                                        \
1498
    if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist))   \
1499
        return;                                                                                   \
1500
    probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK;                                         \
1501
    if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) \
1502
        break;
1503
            TDEFL_PROBE;
1504
            TDEFL_PROBE;
1505
            TDEFL_PROBE;
1506
        }
1507
        if (!dist)
1508
            break;
1509
        p = s;
1510
        q = d->m_dict + probe_pos;
1511
        for (probe_len = 0; probe_len < max_match_len; probe_len++)
1512
            if (*p++ != *q++)
1513
                break;
1514
        if (probe_len > match_len)
1515
        {
1516
            *pMatch_dist = dist;
1517
            if ((*pMatch_len = match_len = probe_len) == max_match_len)
1518
                return;
1519
            c0 = d->m_dict[pos + match_len];
1520
            c1 = d->m_dict[pos + match_len - 1];
1521
        }
1522
    }
1523
}
1524
#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES */
1525

1526
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1527
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
1528
static mz_uint32 TDEFL_READ_UNALIGNED_WORD32(const mz_uint8* p)
1529
{
1530
	mz_uint32 ret;
1531
	memcpy(&ret, p, sizeof(mz_uint32));
1532
	return ret;
1533
}
1534
#else
1535
#define TDEFL_READ_UNALIGNED_WORD32(p) *(const mz_uint32 *)(p)
1536
#endif
1537
static mz_bool tdefl_compress_fast(tdefl_compressor *d)
1538
{
1539
    /* Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. */
1540
    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;
1541
    mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags;
1542
    mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1543

1544
    while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size)))
1545
    {
1546
        const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096;
1547
        mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1548
        mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size);
1549
        d->m_src_buf_left -= num_bytes_to_process;
1550
        lookahead_size += num_bytes_to_process;
1551

1552
        while (num_bytes_to_process)
1553
        {
1554
            mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process);
1555
            memcpy(d->m_dict + dst_pos, d->m_pSrc, n);
1556
            if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1557
                memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos));
1558
            d->m_pSrc += n;
1559
            dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK;
1560
            num_bytes_to_process -= n;
1561
        }
1562

1563
        dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size);
1564
        if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE))
1565
            break;
1566

1567
        while (lookahead_size >= 4)
1568
        {
1569
            mz_uint cur_match_dist, cur_match_len = 1;
1570
            mz_uint8 *pCur_dict = d->m_dict + cur_pos;
1571
            mz_uint first_trigram = TDEFL_READ_UNALIGNED_WORD32(pCur_dict) & 0xFFFFFF;
1572
            mz_uint hash = (first_trigram ^ (first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK;
1573
            mz_uint probe_pos = d->m_hash[hash];
1574
            d->m_hash[hash] = (mz_uint16)lookahead_pos;
1575

1576
            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))
1577
            {
1578
                const mz_uint16 *p = (const mz_uint16 *)pCur_dict;
1579
                const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos);
1580
                mz_uint32 probe_len = 32;
1581
                do
1582
                {
1583
                } while ((TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) &&
1584
                         (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (TDEFL_READ_UNALIGNED_WORD2(++p) == TDEFL_READ_UNALIGNED_WORD2(++q)) && (--probe_len > 0));
1585
                cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q);
1586
                if (!probe_len)
1587
                    cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0;
1588

1589
                if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U * 1024U)))
1590
                {
1591
                    cur_match_len = 1;
1592
                    *pLZ_code_buf++ = (mz_uint8)first_trigram;
1593
                    *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1594
                    d->m_huff_count[0][(mz_uint8)first_trigram]++;
1595
                }
1596
                else
1597
                {
1598
                    mz_uint32 s0, s1;
1599
                    cur_match_len = MZ_MIN(cur_match_len, lookahead_size);
1600

1601
                    MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE));
1602

1603
                    cur_match_dist--;
1604

1605
                    pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN);
1606
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
1607
					memcpy(&pLZ_code_buf[1], &cur_match_dist, sizeof(cur_match_dist));
1608
#else
1609
                    *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist;
1610
#endif
1611
                    pLZ_code_buf += 3;
1612
                    *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80);
1613

1614
                    s0 = s_tdefl_small_dist_sym[cur_match_dist & 511];
1615
                    s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8];
1616
                    d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++;
1617

1618
                    d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++;
1619
                }
1620
            }
1621
            else
1622
            {
1623
                *pLZ_code_buf++ = (mz_uint8)first_trigram;
1624
                *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1625
                d->m_huff_count[0][(mz_uint8)first_trigram]++;
1626
            }
1627

1628
            if (--num_flags_left == 0)
1629
            {
1630
                num_flags_left = 8;
1631
                pLZ_flags = pLZ_code_buf++;
1632
            }
1633

1634
            total_lz_bytes += cur_match_len;
1635
            lookahead_pos += cur_match_len;
1636
            dict_size = MZ_MIN(dict_size + cur_match_len, (mz_uint)TDEFL_LZ_DICT_SIZE);
1637
            cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK;
1638
            MZ_ASSERT(lookahead_size >= cur_match_len);
1639
            lookahead_size -= cur_match_len;
1640

1641
            if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1642
            {
1643
                int n;
1644
                d->m_lookahead_pos = lookahead_pos;
1645
                d->m_lookahead_size = lookahead_size;
1646
                d->m_dict_size = dict_size;
1647
                d->m_total_lz_bytes = total_lz_bytes;
1648
                d->m_pLZ_code_buf = pLZ_code_buf;
1649
                d->m_pLZ_flags = pLZ_flags;
1650
                d->m_num_flags_left = num_flags_left;
1651
                if ((n = tdefl_flush_block(d, 0)) != 0)
1652
                    return (n < 0) ? MZ_FALSE : MZ_TRUE;
1653
                total_lz_bytes = d->m_total_lz_bytes;
1654
                pLZ_code_buf = d->m_pLZ_code_buf;
1655
                pLZ_flags = d->m_pLZ_flags;
1656
                num_flags_left = d->m_num_flags_left;
1657
            }
1658
        }
1659

1660
        while (lookahead_size)
1661
        {
1662
            mz_uint8 lit = d->m_dict[cur_pos];
1663

1664
            total_lz_bytes++;
1665
            *pLZ_code_buf++ = lit;
1666
            *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1);
1667
            if (--num_flags_left == 0)
1668
            {
1669
                num_flags_left = 8;
1670
                pLZ_flags = pLZ_code_buf++;
1671
            }
1672

1673
            d->m_huff_count[0][lit]++;
1674

1675
            lookahead_pos++;
1676
            dict_size = MZ_MIN(dict_size + 1, (mz_uint)TDEFL_LZ_DICT_SIZE);
1677
            cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1678
            lookahead_size--;
1679

1680
            if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8])
1681
            {
1682
                int n;
1683
                d->m_lookahead_pos = lookahead_pos;
1684
                d->m_lookahead_size = lookahead_size;
1685
                d->m_dict_size = dict_size;
1686
                d->m_total_lz_bytes = total_lz_bytes;
1687
                d->m_pLZ_code_buf = pLZ_code_buf;
1688
                d->m_pLZ_flags = pLZ_flags;
1689
                d->m_num_flags_left = num_flags_left;
1690
                if ((n = tdefl_flush_block(d, 0)) != 0)
1691
                    return (n < 0) ? MZ_FALSE : MZ_TRUE;
1692
                total_lz_bytes = d->m_total_lz_bytes;
1693
                pLZ_code_buf = d->m_pLZ_code_buf;
1694
                pLZ_flags = d->m_pLZ_flags;
1695
                num_flags_left = d->m_num_flags_left;
1696
            }
1697
        }
1698
    }
1699

1700
    d->m_lookahead_pos = lookahead_pos;
1701
    d->m_lookahead_size = lookahead_size;
1702
    d->m_dict_size = dict_size;
1703
    d->m_total_lz_bytes = total_lz_bytes;
1704
    d->m_pLZ_code_buf = pLZ_code_buf;
1705
    d->m_pLZ_flags = pLZ_flags;
1706
    d->m_num_flags_left = num_flags_left;
1707
    return MZ_TRUE;
1708
}
1709
#endif /* MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1710

1711
static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit)
1712
{
1713
    d->m_total_lz_bytes++;
1714
    *d->m_pLZ_code_buf++ = lit;
1715
    // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
1716
    *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1);
1717
    if (--d->m_num_flags_left == 0)
1718
    {
1719
        d->m_num_flags_left = 8;
1720
        d->m_pLZ_flags = d->m_pLZ_code_buf++;
1721
    }
1722
    d->m_huff_count[0][lit]++;
1723
}
1724

1725
static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist)
1726
{
1727
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1728
    mz_uint32 s0, s1;
1729

1730
    MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE));
1731

1732
    d->m_total_lz_bytes += match_len;
1733

1734
    d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN);
1735

1736
    match_dist -= 1;
1737
    d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF);
1738
    d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8);
1739
    d->m_pLZ_code_buf += 3;
1740

1741
    *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80);
1742
    if (--d->m_num_flags_left == 0)
1743
    {
1744
        d->m_num_flags_left = 8;
1745
        d->m_pLZ_flags = d->m_pLZ_code_buf++;
1746
    }
1747

1748
    s0 = s_tdefl_small_dist_sym[match_dist & 511];
1749
    s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127];
1750
    d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++;
1751

1752
    if (match_len >= TDEFL_MIN_MATCH_LEN)
1753
        d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++;
1754
}
1755

1756
static mz_bool tdefl_compress_normal(tdefl_compressor *d)
1757
{
1758
    const mz_uint8 *pSrc = d->m_pSrc;
1759
    size_t src_buf_left = d->m_src_buf_left;
1760
    tdefl_flush flush = d->m_flush;
1761

1762
    while ((src_buf_left) || ((flush) && (d->m_lookahead_size)))
1763
    {
1764
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1765
        mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos;
1766
        /* Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. */
1767
        if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1))
1768
        {
1769
            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;
1770
            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];
1771
            mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size);
1772
            const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process;
1773
            src_buf_left -= num_bytes_to_process;
1774
            d->m_lookahead_size += num_bytes_to_process;
1775
            while (pSrc != pSrc_end)
1776
            {
1777
                mz_uint8 c = *pSrc++;
1778
                d->m_dict[dst_pos] = c;
1779
                if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1780
                    d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1781
                hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1);
1782
                d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1783
                d->m_hash[hash] = (mz_uint16)(ins_pos);
1784
                dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK;
1785
                ins_pos++;
1786
            }
1787
        }
1788
        else
1789
        {
1790
            while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1791
            {
1792
                mz_uint8 c = *pSrc++;
1793
                mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK;
1794
                src_buf_left--;
1795
                d->m_dict[dst_pos] = c;
1796
                if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1))
1797
                    d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c;
1798
                if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN)
1799
                {
1800
                    mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2;
1801
                    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);
1802
                    d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash];
1803
                    d->m_hash[hash] = (mz_uint16)(ins_pos);
1804
                }
1805
            }
1806
        }
1807
        d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size);
1808
        if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN))
1809
            break;
1810

1811
        /* Simple lazy/greedy parsing state machine. */
1812
        len_to_move = 1;
1813
        cur_match_dist = 0;
1814
        cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1);
1815
        cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK;
1816
        if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS))
1817
        {
1818
            if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))
1819
            {
1820
                mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK];
1821
                cur_match_len = 0;
1822
                while (cur_match_len < d->m_lookahead_size)
1823
                {
1824
                    if (d->m_dict[cur_pos + cur_match_len] != c)
1825
                        break;
1826
                    cur_match_len++;
1827
                }
1828
                if (cur_match_len < TDEFL_MIN_MATCH_LEN)
1829
                    cur_match_len = 0;
1830
                else
1831
                    cur_match_dist = 1;
1832
            }
1833
        }
1834
        else
1835
        {
1836
            tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len);
1837
        }
1838
        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)))
1839
        {
1840
            cur_match_dist = cur_match_len = 0;
1841
        }
1842
        if (d->m_saved_match_len)
1843
        {
1844
            if (cur_match_len > d->m_saved_match_len)
1845
            {
1846
                tdefl_record_literal(d, (mz_uint8)d->m_saved_lit);
1847
                if (cur_match_len >= 128)
1848
                {
1849
                    tdefl_record_match(d, cur_match_len, cur_match_dist);
1850
                    d->m_saved_match_len = 0;
1851
                    len_to_move = cur_match_len;
1852
                }
1853
                else
1854
                {
1855
                    d->m_saved_lit = d->m_dict[cur_pos];
1856
                    d->m_saved_match_dist = cur_match_dist;
1857
                    d->m_saved_match_len = cur_match_len;
1858
                }
1859
            }
1860
            else
1861
            {
1862
                tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist);
1863
                len_to_move = d->m_saved_match_len - 1;
1864
                d->m_saved_match_len = 0;
1865
            }
1866
        }
1867
        else if (!cur_match_dist)
1868
            tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]);
1869
        else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128))
1870
        {
1871
            tdefl_record_match(d, cur_match_len, cur_match_dist);
1872
            len_to_move = cur_match_len;
1873
        }
1874
        else
1875
        {
1876
            d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)];
1877
            d->m_saved_match_dist = cur_match_dist;
1878
            d->m_saved_match_len = cur_match_len;
1879
        }
1880
        /* Move the lookahead forward by len_to_move bytes. */
1881
        d->m_lookahead_pos += len_to_move;
1882
        MZ_ASSERT(d->m_lookahead_size >= len_to_move);
1883
        d->m_lookahead_size -= len_to_move;
1884
        d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, (mz_uint)TDEFL_LZ_DICT_SIZE);
1885
        /* Check if it's time to flush the current LZ codes to the internal output buffer. */
1886
        if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) ||
1887
            ((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))))
1888
        {
1889
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
1890
            int n;
1891
            d->m_pSrc = pSrc;
1892
            d->m_src_buf_left = src_buf_left;
1893
            if ((n = tdefl_flush_block(d, 0)) != 0)
1894
                return (n < 0) ? MZ_FALSE : MZ_TRUE;
1895
        }
1896
    }
1897

1898
    d->m_pSrc = pSrc;
1899
    d->m_src_buf_left = src_buf_left;
1900
    return MZ_TRUE;
1901
}
1902

1903
static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d)
1904
{
1905
    if (d->m_pIn_buf_size)
1906
    {
1907
        *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf;
1908
    }
1909

1910
    if (d->m_pOut_buf_size)
1911
    {
1912
        size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining);
1913
        memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n);
1914
        d->m_output_flush_ofs += (mz_uint)n;
1915
        d->m_output_flush_remaining -= (mz_uint)n;
1916
        d->m_out_buf_ofs += n;
1917

1918
        *d->m_pOut_buf_size = d->m_out_buf_ofs;
1919
    }
1920

1921
    return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY;
1922
}
1923

1924
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)
1925
{
1926
    if (!d)
1927
    {
1928
        if (pIn_buf_size)
1929
            *pIn_buf_size = 0;
1930
        if (pOut_buf_size)
1931
            *pOut_buf_size = 0;
1932
        return TDEFL_STATUS_BAD_PARAM;
1933
    }
1934

1935
    d->m_pIn_buf = pIn_buf;
1936
    d->m_pIn_buf_size = pIn_buf_size;
1937
    d->m_pOut_buf = pOut_buf;
1938
    d->m_pOut_buf_size = pOut_buf_size;
1939
    d->m_pSrc = (const mz_uint8 *)(pIn_buf);
1940
    d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0;
1941
    d->m_out_buf_ofs = 0;
1942
    d->m_flush = flush;
1943

1944
    if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) ||
1945
        (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf))
1946
    {
1947
        if (pIn_buf_size)
1948
            *pIn_buf_size = 0;
1949
        if (pOut_buf_size)
1950
            *pOut_buf_size = 0;
1951
        return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM);
1952
    }
1953
    d->m_wants_to_finish |= (flush == TDEFL_FINISH);
1954

1955
    if ((d->m_output_flush_remaining) || (d->m_finished))
1956
        return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1957

1958
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
1959
    if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) &&
1960
        ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) &&
1961
        ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0))
1962
    {
1963
        if (!tdefl_compress_fast(d))
1964
            return d->m_prev_return_status;
1965
    }
1966
    else
1967
#endif /* #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN */
1968
    {
1969
        if (!tdefl_compress_normal(d))
1970
            return d->m_prev_return_status;
1971
    }
1972

1973
    if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf))
1974
        d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf);
1975

1976
    if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining))
1977
    {
1978
        if (tdefl_flush_block(d, flush) < 0)
1979
            return d->m_prev_return_status;
1980
        d->m_finished = (flush == TDEFL_FINISH);
1981
        if (flush == TDEFL_FULL_FLUSH)
1982
        {
1983
            MZ_CLEAR_OBJ(d->m_hash);
1984
            MZ_CLEAR_OBJ(d->m_next);
1985
            d->m_dict_size = 0;
1986
        }
1987
    }
1988

1989
    return (d->m_prev_return_status = tdefl_flush_output_buffer(d));
1990
}
1991

1992
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush)
1993
{
1994
    MZ_ASSERT(d->m_pPut_buf_func);
1995
    return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush);
1996
}
1997

1998
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags)
1999
{
2000
    d->m_pPut_buf_func = pPut_buf_func;
2001
    d->m_pPut_buf_user = pPut_buf_user;
2002
    d->m_flags = (mz_uint)(flags);
2003
    d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3;
2004
    d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0;
2005
    d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3;
2006
    if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
2007
        MZ_CLEAR_OBJ(d->m_hash);
2008
    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;
2009
    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;
2010
    d->m_pLZ_code_buf = d->m_lz_code_buf + 1;
2011
    d->m_pLZ_flags = d->m_lz_code_buf;
2012
    d->m_num_flags_left = 8;
2013
    d->m_pOutput_buf = d->m_output_buf;
2014
    d->m_pOutput_buf_end = d->m_output_buf;
2015
    d->m_prev_return_status = TDEFL_STATUS_OKAY;
2016
    d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0;
2017
    d->m_adler32 = 1;
2018
    d->m_pIn_buf = NULL;
2019
    d->m_pOut_buf = NULL;
2020
    d->m_pIn_buf_size = NULL;
2021
    d->m_pOut_buf_size = NULL;
2022
    d->m_flush = TDEFL_NO_FLUSH;
2023
    d->m_pSrc = NULL;
2024
    d->m_src_buf_left = 0;
2025
    d->m_out_buf_ofs = 0;
2026
    if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG))
2027
        MZ_CLEAR_OBJ(d->m_dict);
2028
    memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0);
2029
    memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1);
2030
    return TDEFL_STATUS_OKAY;
2031
}
2032

2033
tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d)
2034
{
2035
    return d->m_prev_return_status;
2036
}
2037

2038
mz_uint32 tdefl_get_adler32(tdefl_compressor *d)
2039
{
2040
    return d->m_adler32;
2041
}
2042

2043
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)
2044
{
2045
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2046
    tdefl_compressor *pComp;
2047
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2048
    mz_bool succeeded;
2049
    if (((buf_len) && (!pBuf)) || (!pPut_buf_func))
2050
        return MZ_FALSE;
2051
    pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2052
    if (!pComp)
2053
        return MZ_FALSE;
2054
    succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY);
2055
    succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE);
2056
    MZ_FREE(pComp);
2057
    return succeeded;
2058
}
2059

2060
typedef struct
2061
{
2062
    size_t m_size, m_capacity;
2063
    mz_uint8 *m_pBuf;
2064
    mz_bool m_expandable;
2065
} tdefl_output_buffer;
2066

2067
static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser)
2068
{
2069
    tdefl_output_buffer *p = (tdefl_output_buffer *)pUser;
2070
    size_t new_size = p->m_size + len;
2071
    if (new_size > p->m_capacity)
2072
    {
2073
        size_t new_capacity = p->m_capacity;
2074
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2075
        mz_uint8 *pNew_buf;
2076
        if (!p->m_expandable)
2077
            return MZ_FALSE;
2078
        do
2079
        {
2080
            new_capacity = MZ_MAX(128U, new_capacity << 1U);
2081
        } while (new_size > new_capacity);
2082
        pNew_buf = (mz_uint8 *)MZ_REALLOC(p->m_pBuf, new_capacity);
2083
        if (!pNew_buf)
2084
            return MZ_FALSE;
2085
        p->m_pBuf = pNew_buf;
2086
        p->m_capacity = new_capacity;
2087
    }
2088
    memcpy((mz_uint8 *)p->m_pBuf + p->m_size, pBuf, len);
2089
    p->m_size = new_size;
2090
    return MZ_TRUE;
2091
}
2092

2093
void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2094
{
2095
    tdefl_output_buffer out_buf;
2096
    MZ_CLEAR_OBJ(out_buf);
2097
    if (!pOut_len)
2098
        return MZ_FALSE;
2099
    else
2100
        *pOut_len = 0;
2101
    out_buf.m_expandable = MZ_TRUE;
2102
    if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2103
        return NULL;
2104
    *pOut_len = out_buf.m_size;
2105
    return out_buf.m_pBuf;
2106
}
2107

2108
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)
2109
{
2110
    tdefl_output_buffer out_buf;
2111
    MZ_CLEAR_OBJ(out_buf);
2112
    if (!pOut_buf)
2113
        return 0;
2114
    out_buf.m_pBuf = (mz_uint8 *)pOut_buf;
2115
    out_buf.m_capacity = out_buf_len;
2116
    if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags))
2117
        return 0;
2118
    return out_buf.m_size;
2119
}
2120

2121
static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2122

2123
/* 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). */
2124
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy)
2125
{
2126
    mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
2127
    if (window_bits > 0)
2128
        comp_flags |= TDEFL_WRITE_ZLIB_HEADER;
2129

2130
    if (!level)
2131
        comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
2132
    else if (strategy == MZ_FILTERED)
2133
        comp_flags |= TDEFL_FILTER_MATCHES;
2134
    else if (strategy == MZ_HUFFMAN_ONLY)
2135
        comp_flags &= ~TDEFL_MAX_PROBES_MASK;
2136
    else if (strategy == MZ_FIXED)
2137
        comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS;
2138
    else if (strategy == MZ_RLE)
2139
        comp_flags |= TDEFL_RLE_MATCHES;
2140

2141
    return comp_flags;
2142
}
2143

2144
#ifdef _MSC_VER
2145
#pragma warning(push)
2146
#pragma warning(disable : 4204) /* nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) */
2147
#endif
2148

2149
/* Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at
2150
 http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/.
2151
 This is actually a modification of Alex's original code so PNG files generated by this function pass pngcheck. */
2152
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)
2153
{
2154
    /* Using a local copy of this array here in case MINIZ_NO_ZLIB_APIS was defined. */
2155
    static const mz_uint s_tdefl_png_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
2156
    tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2157
    tdefl_output_buffer out_buf;
2158
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2159
    int i, bpl = w * num_chans, y, z;
2160
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2161
    mz_uint32 c;
2162
    *pLen_out = 0;
2163
    if (!pComp)
2164
        return NULL;
2165
    MZ_CLEAR_OBJ(out_buf);
2166
    out_buf.m_expandable = MZ_TRUE;
2167
    out_buf.m_capacity = 57 + MZ_MAX(64, (1 + bpl) * h);
2168
    if (NULL == (out_buf.m_pBuf = (mz_uint8 *)MZ_MALLOC(out_buf.m_capacity)))
2169
    {
2170
        MZ_FREE(pComp);
2171
        return NULL;
2172
    }
2173
    /* write dummy header */
2174
    for (z = 41; z; --z)
2175
        tdefl_output_buffer_putter(&z, 1, &out_buf);
2176
    /* compress image data */
2177
    // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
2178
    tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, s_tdefl_png_num_probes[MZ_MIN(10, level)] | TDEFL_WRITE_ZLIB_HEADER);
2179
    for (y = 0; y < h; ++y)
2180
    {
2181
        tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH);
2182
        tdefl_compress_buffer(pComp, (mz_uint8 *)pImage + (flip ? (h - 1 - y) : y) * bpl, bpl, TDEFL_NO_FLUSH);
2183
    }
2184
    if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE)
2185
    {
2186
        MZ_FREE(pComp);
2187
        MZ_FREE(out_buf.m_pBuf);
2188
        return NULL;
2189
    }
2190
    /* write real header */
2191
    *pLen_out = out_buf.m_size - 41;
2192
    {
2193
        static const mz_uint8 chans[] = { 0x00, 0x00, 0x04, 0x02, 0x06 };
2194
        mz_uint8 pnghdr[41] = { 0x89, 0x50, 0x4e, 0x47, 0x0d,
2195
                                0x0a, 0x1a, 0x0a, 0x00, 0x00,
2196
                                0x00, 0x0d, 0x49, 0x48, 0x44,
2197
                                0x52, 0x00, 0x00, 0x00, 0x00,
2198
                                0x00, 0x00, 0x00, 0x00, 0x08,
2199
                                0x00, 0x00, 0x00, 0x00, 0x00,
2200
                                0x00, 0x00, 0x00, 0x00, 0x00,
2201
                                0x00, 0x00, 0x49, 0x44, 0x41,
2202
                                0x54 };
2203
        pnghdr[18] = (mz_uint8)(w >> 8);
2204
        pnghdr[19] = (mz_uint8)w;
2205
        pnghdr[22] = (mz_uint8)(h >> 8);
2206
        pnghdr[23] = (mz_uint8)h;
2207
        pnghdr[25] = chans[num_chans];
2208
        pnghdr[33] = (mz_uint8)(*pLen_out >> 24);
2209
        pnghdr[34] = (mz_uint8)(*pLen_out >> 16);
2210
        pnghdr[35] = (mz_uint8)(*pLen_out >> 8);
2211
        pnghdr[36] = (mz_uint8)*pLen_out;
2212
        c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, pnghdr + 12, 17);
2213
        for (i = 0; i < 4; ++i, c <<= 8)
2214
            ((mz_uint8 *)(pnghdr + 29))[i] = (mz_uint8)(c >> 24);
2215
        memcpy(out_buf.m_pBuf, pnghdr, 41);
2216
    }
2217
    /* write footer (IDAT CRC-32, followed by IEND chunk) */
2218
    if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf))
2219
    {
2220
        *pLen_out = 0;
2221
        MZ_FREE(pComp);
2222
        MZ_FREE(out_buf.m_pBuf);
2223
        return NULL;
2224
    }
2225
    c = (mz_uint32)mz_crc32(MZ_CRC32_INIT, out_buf.m_pBuf + 41 - 4, *pLen_out + 4);
2226
    for (i = 0; i < 4; ++i, c <<= 8)
2227
        (out_buf.m_pBuf + out_buf.m_size - 16)[i] = (mz_uint8)(c >> 24);
2228
    /* compute final size of file, grab compressed data buffer and return */
2229
    *pLen_out += 57;
2230
    MZ_FREE(pComp);
2231
    return out_buf.m_pBuf;
2232
}
2233
void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out)
2234
{
2235
    /* 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) */
2236
    return tdefl_write_image_to_png_file_in_memory_ex(pImage, w, h, num_chans, pLen_out, 6, MZ_FALSE);
2237
}
2238

2239
#ifndef MINIZ_NO_MALLOC
2240
/* Allocate the tdefl_compressor and tinfl_decompressor structures in C so that */
2241
/* non-C language bindings to tdefL_ and tinfl_ API don't need to worry about */
2242
/* structure size and allocation mechanism. */
2243
tdefl_compressor *tdefl_compressor_alloc(void)
2244
{
2245
    return (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor));
2246
}
2247

2248
void tdefl_compressor_free(tdefl_compressor *pComp)
2249
{
2250
    MZ_FREE(pComp);
2251
}
2252
#endif
2253

2254
#ifdef _MSC_VER
2255
#pragma warning(pop)
2256
#endif
2257

2258
#ifdef __cplusplus
2259
}
2260
#endif
2261
/**************************************************************************
2262
 *
2263
 * Copyright 2013-2014 RAD Game Tools and Valve Software
2264
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
2265
 * All Rights Reserved.
2266
 *
2267
 * Permission is hereby granted, free of charge, to any person obtaining a copy
2268
 * of this software and associated documentation files (the "Software"), to deal
2269
 * in the Software without restriction, including without limitation the rights
2270
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2271
 * copies of the Software, and to permit persons to whom the Software is
2272
 * furnished to do so, subject to the following conditions:
2273
 *
2274
 * The above copyright notice and this permission notice shall be included in
2275
 * all copies or substantial portions of the Software.
2276
 *
2277
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2278
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2279
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2280
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2281
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2282
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2283
 * THE SOFTWARE.
2284
 *
2285
 **************************************************************************/
2286

2287

2288

2289
#ifdef __cplusplus
2290
extern "C" {
2291
#endif
2292

2293
/* ------------------- Low-level Decompression (completely independent from all compression API's) */
2294

2295
#define TINFL_MEMCPY(d, s, l) memcpy(d, s, l)
2296
#define TINFL_MEMSET(p, c, l) memset(p, c, l)
2297

2298
#define TINFL_CR_BEGIN  \
2299
    switch (r->m_state) \
2300
    {                   \
2301
        case 0:
2302
#define TINFL_CR_RETURN(state_index, result) \
2303
    do                                       \
2304
    {                                        \
2305
        status = result;                     \
2306
        r->m_state = state_index;            \
2307
        goto common_exit;                    \
2308
        case state_index:;                   \
2309
    }                                        \
2310
    MZ_MACRO_END
2311
#define TINFL_CR_RETURN_FOREVER(state_index, result) \
2312
    do                                               \
2313
    {                                                \
2314
        for (;;)                                     \
2315
        {                                            \
2316
            TINFL_CR_RETURN(state_index, result);    \
2317
        }                                            \
2318
    }                                                \
2319
    MZ_MACRO_END
2320
#define TINFL_CR_FINISH }
2321

2322
#define TINFL_GET_BYTE(state_index, c)                                                                                                                           \
2323
    do                                                                                                                                                           \
2324
    {                                                                                                                                                            \
2325
        while (pIn_buf_cur >= pIn_buf_end)                                                                                                                       \
2326
        {                                                                                                                                                        \
2327
            TINFL_CR_RETURN(state_index, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS); \
2328
        }                                                                                                                                                        \
2329
        c = *pIn_buf_cur++;                                                                                                                                      \
2330
    }                                                                                                                                                            \
2331
    MZ_MACRO_END
2332

2333
#define TINFL_NEED_BITS(state_index, n)                \
2334
    do                                                 \
2335
    {                                                  \
2336
        mz_uint c;                                     \
2337
        TINFL_GET_BYTE(state_index, c);                \
2338
        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); \
2339
        num_bits += 8;                                 \
2340
    } while (num_bits < (mz_uint)(n))
2341
#define TINFL_SKIP_BITS(state_index, n)      \
2342
    do                                       \
2343
    {                                        \
2344
        if (num_bits < (mz_uint)(n))         \
2345
        {                                    \
2346
            TINFL_NEED_BITS(state_index, n); \
2347
        }                                    \
2348
        bit_buf >>= (n);                     \
2349
        num_bits -= (n);                     \
2350
    }                                        \
2351
    MZ_MACRO_END
2352
#define TINFL_GET_BITS(state_index, b, n)    \
2353
    do                                       \
2354
    {                                        \
2355
        if (num_bits < (mz_uint)(n))         \
2356
        {                                    \
2357
            TINFL_NEED_BITS(state_index, n); \
2358
        }                                    \
2359
        b = bit_buf & ((1 << (n)) - 1);      \
2360
        bit_buf >>= (n);                     \
2361
        num_bits -= (n);                     \
2362
    }                                        \
2363
    MZ_MACRO_END
2364

2365
/* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. */
2366
/* 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 */
2367
/* 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 */
2368
/* bit buffer contains >=15 bits (deflate's max. Huffman code size). */
2369
#define TINFL_HUFF_BITBUF_FILL(state_index, pHuff)                             \
2370
    do                                                                         \
2371
    {                                                                          \
2372
        temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)];     \
2373
        if (temp >= 0)                                                         \
2374
        {                                                                      \
2375
            code_len = temp >> 9;                                              \
2376
            if ((code_len) && (num_bits >= code_len))                          \
2377
                break;                                                         \
2378
        }                                                                      \
2379
        else if (num_bits > TINFL_FAST_LOOKUP_BITS)                            \
2380
        {                                                                      \
2381
            code_len = TINFL_FAST_LOOKUP_BITS;                                 \
2382
            do                                                                 \
2383
            {                                                                  \
2384
                temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \
2385
            } while ((temp < 0) && (num_bits >= (code_len + 1)));              \
2386
            if (temp >= 0)                                                     \
2387
                break;                                                         \
2388
        }                                                                      \
2389
        TINFL_GET_BYTE(state_index, c);                                        \
2390
        bit_buf |= (((tinfl_bit_buf_t)c) << num_bits);                         \
2391
        num_bits += 8;                                                         \
2392
    } while (num_bits < 15);
2393

2394
/* 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 */
2395
/* 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 */
2396
/* 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. */
2397
/* The slow path is only executed at the very end of the input buffer. */
2398
/* 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 */
2399
/* following the deflate data and our non-conservative read-ahead path won't kick in here on this code. This is much trickier. */
2400
#define TINFL_HUFF_DECODE(state_index, sym, pHuff)                                                                                  \
2401
    do                                                                                                                              \
2402
    {                                                                                                                               \
2403
        int temp;                                                                                                                   \
2404
        mz_uint code_len, c;                                                                                                        \
2405
        if (num_bits < 15)                                                                                                          \
2406
        {                                                                                                                           \
2407
            if ((pIn_buf_end - pIn_buf_cur) < 2)                                                                                    \
2408
            {                                                                                                                       \
2409
                TINFL_HUFF_BITBUF_FILL(state_index, pHuff);                                                                         \
2410
            }                                                                                                                       \
2411
            else                                                                                                                    \
2412
            {                                                                                                                       \
2413
                bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); \
2414
                pIn_buf_cur += 2;                                                                                                   \
2415
                num_bits += 16;                                                                                                     \
2416
            }                                                                                                                       \
2417
        }                                                                                                                           \
2418
        if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)                                               \
2419
            code_len = temp >> 9, temp &= 511;                                                                                      \
2420
        else                                                                                                                        \
2421
        {                                                                                                                           \
2422
            code_len = TINFL_FAST_LOOKUP_BITS;                                                                                      \
2423
            do                                                                                                                      \
2424
            {                                                                                                                       \
2425
                temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)];                                                      \
2426
            } while (temp < 0);                                                                                                     \
2427
        }                                                                                                                           \
2428
        sym = temp;                                                                                                                 \
2429
        bit_buf >>= code_len;                                                                                                       \
2430
        num_bits -= code_len;                                                                                                       \
2431
    }                                                                                                                               \
2432
    MZ_MACRO_END
2433

2434
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)
2435
{
2436
    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 };
2437
    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 };
2438
    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 };
2439
    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 };
2440
    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 };
2441
    static const int s_min_table_sizes[3] = { 257, 1, 4 };
2442

2443
    tinfl_status status = TINFL_STATUS_FAILED;
2444
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2445
    mz_uint32 num_bits, dist, counter, num_extra;
2446
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2447
    tinfl_bit_buf_t bit_buf;
2448
    const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size;
2449
    mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size;
2450
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2451
    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;
2452

2453
    /* 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). */
2454
    if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start))
2455
    {
2456
        *pIn_buf_size = *pOut_buf_size = 0;
2457
        return TINFL_STATUS_BAD_PARAM;
2458
    }
2459

2460
    num_bits = r->m_num_bits;
2461
    bit_buf = r->m_bit_buf;
2462
    dist = r->m_dist;
2463
    counter = r->m_counter;
2464
    num_extra = r->m_num_extra;
2465
    dist_from_out_buf_start = r->m_dist_from_out_buf_start;
2466
    TINFL_CR_BEGIN
2467

2468
    bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0;
2469
    r->m_z_adler32 = r->m_check_adler32 = 1;
2470
    if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2471
    {
2472
        TINFL_GET_BYTE(1, r->m_zhdr0);
2473
        TINFL_GET_BYTE(2, r->m_zhdr1);
2474
        counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8));
2475
        if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2476
            // NOLINTNEXTLINE(bugprone-misplaced-widening-cast,cppcoreguidelines-avoid-magic-numbers)
2477
            counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4)))));
2478
        if (counter)
2479
        {
2480
            TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED);
2481
        }
2482
    }
2483

2484
    do
2485
    {
2486
        TINFL_GET_BITS(3, r->m_final, 3);
2487
        r->m_type = r->m_final >> 1;
2488
        if (r->m_type == 0)
2489
        {
2490
            TINFL_SKIP_BITS(5, num_bits & 7);
2491
            for (counter = 0; counter < 4; ++counter)
2492
            {
2493
                if (num_bits)
2494
                    TINFL_GET_BITS(6, r->m_raw_header[counter], 8);
2495
                else
2496
                    TINFL_GET_BYTE(7, r->m_raw_header[counter]);
2497
            }
2498
            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))))
2499
            {
2500
                TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED);
2501
            }
2502
            while ((counter) && (num_bits))
2503
            {
2504
                TINFL_GET_BITS(51, dist, 8);
2505
                while (pOut_buf_cur >= pOut_buf_end)
2506
                {
2507
                    TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT);
2508
                }
2509
                *pOut_buf_cur++ = (mz_uint8)dist;
2510
                counter--;
2511
            }
2512
            while (counter)
2513
            {
2514
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2515
                size_t n;
2516
                while (pOut_buf_cur >= pOut_buf_end)
2517
                {
2518
                    TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT);
2519
                }
2520
                while (pIn_buf_cur >= pIn_buf_end)
2521
                {
2522
                    TINFL_CR_RETURN(38, (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) ? TINFL_STATUS_NEEDS_MORE_INPUT : TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS);
2523
                }
2524
                n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter);
2525
                TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n);
2526
                pIn_buf_cur += n;
2527
                pOut_buf_cur += n;
2528
                counter -= (mz_uint)n;
2529
            }
2530
        }
2531
        else if (r->m_type == 3)
2532
        {
2533
            TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED);
2534
        }
2535
        else
2536
        {
2537
            if (r->m_type == 1)
2538
            {
2539
                mz_uint8 *p = r->m_tables[0].m_code_size;
2540
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2541
                mz_uint i;
2542
                r->m_table_sizes[0] = 288;
2543
                r->m_table_sizes[1] = 32;
2544
                TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32);
2545
                for (i = 0; i <= 143; ++i)
2546
                    *p++ = 8;
2547
                for (; i <= 255; ++i)
2548
                    *p++ = 9;
2549
                for (; i <= 279; ++i)
2550
                    *p++ = 7;
2551
                for (; i <= 287; ++i)
2552
                    *p++ = 8;
2553
            }
2554
            else
2555
            {
2556
                for (counter = 0; counter < 3; counter++)
2557
                {
2558
                    TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]);
2559
                    r->m_table_sizes[counter] += s_min_table_sizes[counter];
2560
                }
2561
                MZ_CLEAR_OBJ(r->m_tables[2].m_code_size);
2562
                for (counter = 0; counter < r->m_table_sizes[2]; counter++)
2563
                {
2564
                    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2565
                    mz_uint s;
2566
                    TINFL_GET_BITS(14, s, 3);
2567
                    r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s;
2568
                }
2569
                r->m_table_sizes[2] = 19;
2570
            }
2571
            for (; (int)r->m_type >= 0; r->m_type--)
2572
            {
2573
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2574
                int tree_next, tree_cur;
2575
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2576
                tinfl_huff_table *pTable;
2577
                // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
2578
                mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16];
2579
                pTable = &r->m_tables[r->m_type];
2580
                MZ_CLEAR_OBJ(total_syms);
2581
                MZ_CLEAR_OBJ(pTable->m_look_up);
2582
                MZ_CLEAR_OBJ(pTable->m_tree);
2583
                for (i = 0; i < r->m_table_sizes[r->m_type]; ++i)
2584
                    total_syms[pTable->m_code_size[i]]++;
2585
                used_syms = 0, total = 0;
2586
                next_code[0] = next_code[1] = 0;
2587
                for (i = 1; i <= 15; ++i)
2588
                {
2589
                    used_syms += total_syms[i];
2590
                    next_code[i + 1] = (total = ((total + total_syms[i]) << 1));
2591
                }
2592
                if ((65536 != total) && (used_syms > 1))
2593
                {
2594
                    TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED);
2595
                }
2596
                for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index)
2597
                {
2598
                    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2599
                    mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index];
2600
                    if (!code_size)
2601
                        continue;
2602
                    cur_code = next_code[code_size]++;
2603
                    for (l = code_size; l > 0; l--, cur_code >>= 1)
2604
                        rev_code = (rev_code << 1) | (cur_code & 1);
2605
                    if (code_size <= TINFL_FAST_LOOKUP_BITS)
2606
                    {
2607
                        mz_int16 k = (mz_int16)((code_size << 9) | sym_index);
2608
                        while (rev_code < TINFL_FAST_LOOKUP_SIZE)
2609
                        {
2610
                            pTable->m_look_up[rev_code] = k;
2611
                            rev_code += (1 << code_size);
2612
                        }
2613
                        continue;
2614
                    }
2615
                    if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)]))
2616
                    {
2617
                        pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next;
2618
                        tree_cur = tree_next;
2619
                        tree_next -= 2;
2620
                    }
2621
                    rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1);
2622
                    for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--)
2623
                    {
2624
                        // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
2625
                        tree_cur -= ((rev_code >>= 1) & 1);
2626
                        if (!pTable->m_tree[-tree_cur - 1])
2627
                        {
2628
                            pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next;
2629
                            tree_cur = tree_next;
2630
                            tree_next -= 2;
2631
                        }
2632
                        else
2633
                            tree_cur = pTable->m_tree[-tree_cur - 1];
2634
                    }
2635
                    // NOLINTNEXTLINE(bugprone-narrowing-conversions,clang-analyzer-deadcode.DeadStores,cppcoreguidelines-narrowing-conversions)
2636
                    tree_cur -= ((rev_code >>= 1) & 1);
2637
                    pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index;
2638
                }
2639
                if (r->m_type == 2)
2640
                {
2641
                    for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);)
2642
                    {
2643
                        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2644
                        mz_uint s;
2645
                        TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]);
2646
                        if (dist < 16)
2647
                        {
2648
                            r->m_len_codes[counter++] = (mz_uint8)dist;
2649
                            continue;
2650
                        }
2651
                        if ((dist == 16) && (!counter))
2652
                        {
2653
                            TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED);
2654
                        }
2655
                        // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,bugprone-signed-char-misuse)
2656
                        num_extra = "\02\03\07"[dist - 16];
2657
                        TINFL_GET_BITS(18, s, num_extra);
2658
                        s += "\03\03\013"[dist - 16];
2659
                        TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s);
2660
                        counter += s;
2661
                    }
2662
                    if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter)
2663
                    {
2664
                        TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED);
2665
                    }
2666
                    TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]);
2667
                    TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]);
2668
                }
2669
            }
2670
            for (;;)
2671
            {
2672
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2673
                mz_uint8 *pSrc;
2674
                for (;;)
2675
                {
2676
                    if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2))
2677
                    {
2678
                        TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]);
2679
                        if (counter >= 256)
2680
                            break;
2681
                        while (pOut_buf_cur >= pOut_buf_end)
2682
                        {
2683
                            TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT);
2684
                        }
2685
                        *pOut_buf_cur++ = (mz_uint8)counter;
2686
                    }
2687
                    else
2688
                    {
2689
                        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2690
                        int sym2;
2691
                        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2692
                        mz_uint code_len;
2693
#if TINFL_USE_64BIT_BITBUF
2694
                        if (num_bits < 30)
2695
                        {
2696
                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits);
2697
                            pIn_buf_cur += 4;
2698
                            num_bits += 32;
2699
                        }
2700
#else
2701
                        if (num_bits < 15)
2702
                        {
2703
                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2704
                            pIn_buf_cur += 2;
2705
                            num_bits += 16;
2706
                        }
2707
#endif
2708
                        if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2709
                            code_len = sym2 >> 9;
2710
                        else
2711
                        {
2712
                            code_len = TINFL_FAST_LOOKUP_BITS;
2713
                            do
2714
                            {
2715
                                sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2716
                            } while (sym2 < 0);
2717
                        }
2718
                        counter = sym2;
2719
                        bit_buf >>= code_len;
2720
                        num_bits -= code_len;
2721
                        if (counter & 256)
2722
                            break;
2723

2724
#if !TINFL_USE_64BIT_BITBUF
2725
                        if (num_bits < 15)
2726
                        {
2727
                            bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits);
2728
                            pIn_buf_cur += 2;
2729
                            num_bits += 16;
2730
                        }
2731
#endif
2732
                        if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0)
2733
                            code_len = sym2 >> 9;
2734
                        else
2735
                        {
2736
                            code_len = TINFL_FAST_LOOKUP_BITS;
2737
                            do
2738
                            {
2739
                                sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)];
2740
                            } while (sym2 < 0);
2741
                        }
2742
                        bit_buf >>= code_len;
2743
                        num_bits -= code_len;
2744

2745
                        pOut_buf_cur[0] = (mz_uint8)counter;
2746
                        if (sym2 & 256)
2747
                        {
2748
                            pOut_buf_cur++;
2749
                            counter = sym2;
2750
                            break;
2751
                        }
2752
                        pOut_buf_cur[1] = (mz_uint8)sym2;
2753
                        pOut_buf_cur += 2;
2754
                    }
2755
                }
2756
                if ((counter &= 511) == 256)
2757
                    break;
2758

2759
                num_extra = s_length_extra[counter - 257];
2760
                counter = s_length_base[counter - 257];
2761
                if (num_extra)
2762
                {
2763
                    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2764
                    mz_uint extra_bits;
2765
                    TINFL_GET_BITS(25, extra_bits, num_extra);
2766
                    counter += extra_bits;
2767
                }
2768

2769
                TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]);
2770
                num_extra = s_dist_extra[dist];
2771
                dist = s_dist_base[dist];
2772
                if (num_extra)
2773
                {
2774
                    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2775
                    mz_uint extra_bits;
2776
                    TINFL_GET_BITS(27, extra_bits, num_extra);
2777
                    dist += extra_bits;
2778
                }
2779

2780
                dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start;
2781
                if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))
2782
                {
2783
                    TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED);
2784
                }
2785

2786
                pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask);
2787

2788
                if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end)
2789
                {
2790
                    while (counter--)
2791
                    {
2792
                        while (pOut_buf_cur >= pOut_buf_end)
2793
                        {
2794
                            TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT);
2795
                        }
2796
                        *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask];
2797
                    }
2798
                    continue;
2799
                }
2800
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES
2801
                else if ((counter >= 9) && (counter <= dist))
2802
                {
2803
                    const mz_uint8 *pSrc_end = pSrc + (counter & ~7);
2804
                    do
2805
                    {
2806
#ifdef MINIZ_UNALIGNED_USE_MEMCPY
2807
						memcpy(pOut_buf_cur, pSrc, sizeof(mz_uint32)*2);
2808
#else
2809
                        ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0];
2810
                        ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1];
2811
#endif
2812
                        pOut_buf_cur += 8;
2813
                    } while ((pSrc += 8) < pSrc_end);
2814
                    if ((counter &= 7) < 3)
2815
                    {
2816
                        if (counter)
2817
                        {
2818
                            pOut_buf_cur[0] = pSrc[0];
2819
                            if (counter > 1)
2820
                                pOut_buf_cur[1] = pSrc[1];
2821
                            pOut_buf_cur += counter;
2822
                        }
2823
                        continue;
2824
                    }
2825
                }
2826
#endif
2827
                while(counter>2)
2828
                {
2829
                    pOut_buf_cur[0] = pSrc[0];
2830
                    pOut_buf_cur[1] = pSrc[1];
2831
                    pOut_buf_cur[2] = pSrc[2];
2832
                    pOut_buf_cur += 3;
2833
                    pSrc += 3;
2834
					counter -= 3;
2835
                }
2836
                if (counter > 0)
2837
                {
2838
                    pOut_buf_cur[0] = pSrc[0];
2839
                    if (counter > 1)
2840
                        pOut_buf_cur[1] = pSrc[1];
2841
                    pOut_buf_cur += counter;
2842
                }
2843
            }
2844
        }
2845
    } while (!(r->m_final & 1));
2846

2847
    /* 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. */
2848
    /* 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. */
2849
    TINFL_SKIP_BITS(32, num_bits & 7);
2850
    while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2851
    {
2852
        --pIn_buf_cur;
2853
        num_bits -= 8;
2854
    }
2855
    bit_buf &= (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2856
    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). */
2857

2858
    if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER)
2859
    {
2860
        for (counter = 0; counter < 4; ++counter)
2861
        {
2862
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2863
            mz_uint s;
2864
            if (num_bits)
2865
                TINFL_GET_BITS(41, s, 8);
2866
            else
2867
                TINFL_GET_BYTE(42, s);
2868
            r->m_z_adler32 = (r->m_z_adler32 << 8) | s;
2869
        }
2870
    }
2871
    TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE);
2872

2873
    TINFL_CR_FINISH
2874

2875
common_exit:
2876
    /* As long as we aren't telling the caller that we NEED more input to make forward progress: */
2877
    /* 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. */
2878
    /* 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. */
2879
    if ((status != TINFL_STATUS_NEEDS_MORE_INPUT) && (status != TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS))
2880
    {
2881
        while ((pIn_buf_cur > pIn_buf_next) && (num_bits >= 8))
2882
        {
2883
            --pIn_buf_cur;
2884
            num_bits -= 8;
2885
        }
2886
    }
2887
    r->m_num_bits = num_bits;
2888
    r->m_bit_buf = bit_buf & (tinfl_bit_buf_t)((((mz_uint64)1) << num_bits) - (mz_uint64)1);
2889
    r->m_dist = dist;
2890
    r->m_counter = counter;
2891
    r->m_num_extra = num_extra;
2892
    r->m_dist_from_out_buf_start = dist_from_out_buf_start;
2893
    *pIn_buf_size = pIn_buf_cur - pIn_buf_next;
2894
    *pOut_buf_size = pOut_buf_cur - pOut_buf_next;
2895
    if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0))
2896
    {
2897
        const mz_uint8 *ptr = pOut_buf_next;
2898
        size_t buf_len = *pOut_buf_size;
2899
        // NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers,cppcoreguidelines-init-variables)
2900
        mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16;
2901
        size_t block_len = buf_len % 5552;
2902
        while (buf_len)
2903
        {
2904
            for (i = 0; i + 7 < block_len; i += 8, ptr += 8)
2905
            {
2906
                s1 += ptr[0], s2 += s1;
2907
                s1 += ptr[1], s2 += s1;
2908
                s1 += ptr[2], s2 += s1;
2909
                s1 += ptr[3], s2 += s1;
2910
                s1 += ptr[4], s2 += s1;
2911
                s1 += ptr[5], s2 += s1;
2912
                s1 += ptr[6], s2 += s1;
2913
                s1 += ptr[7], s2 += s1;
2914
            }
2915
            for (; i < block_len; ++i)
2916
                s1 += *ptr++, s2 += s1;
2917
            s1 %= 65521U, s2 %= 65521U;
2918
            buf_len -= block_len;
2919
            block_len = 5552;
2920
        }
2921
        r->m_check_adler32 = (s2 << 16) + s1;
2922
        if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32))
2923
            status = TINFL_STATUS_ADLER32_MISMATCH;
2924
    }
2925
    return status;
2926
}
2927

2928
/* Higher level helper functions. */
2929
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags)
2930
{
2931
    tinfl_decompressor decomp;
2932
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2933
    void *pBuf = NULL, *pNew_buf;
2934
    size_t src_buf_ofs = 0, out_buf_capacity = 0;
2935
    *pOut_len = 0;
2936
    tinfl_init(&decomp);
2937
    for (;;)
2938
    {
2939
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2940
        size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity;
2941
        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,
2942
                                               (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF);
2943
        if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT))
2944
        {
2945
            MZ_FREE(pBuf);
2946
            *pOut_len = 0;
2947
            return NULL;
2948
        }
2949
        src_buf_ofs += src_buf_size;
2950
        *pOut_len += dst_buf_size;
2951
        if (status == TINFL_STATUS_DONE)
2952
            break;
2953
        new_out_buf_capacity = out_buf_capacity * 2;
2954
        if (new_out_buf_capacity < 128)
2955
            new_out_buf_capacity = 128;
2956
        pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity);
2957
        if (!pNew_buf)
2958
        {
2959
            MZ_FREE(pBuf);
2960
            *pOut_len = 0;
2961
            return NULL;
2962
        }
2963
        pBuf = pNew_buf;
2964
        out_buf_capacity = new_out_buf_capacity;
2965
    }
2966
    return pBuf;
2967
}
2968

2969
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)
2970
{
2971
    tinfl_decompressor decomp;
2972
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
2973
    tinfl_status status;
2974
    tinfl_init(&decomp);
2975
    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);
2976
    return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len;
2977
}
2978

2979
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)
2980
{
2981
    int result = 0;
2982
    tinfl_decompressor decomp;
2983
    mz_uint8 *pDict = (mz_uint8 *)MZ_MALLOC(TINFL_LZ_DICT_SIZE);
2984
    size_t in_buf_ofs = 0, dict_ofs = 0;
2985
    if (!pDict)
2986
        return TINFL_STATUS_FAILED;
2987
    tinfl_init(&decomp);
2988
    for (;;)
2989
    {
2990
        size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs;
2991
        tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8 *)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size,
2992
                                               (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)));
2993
        in_buf_ofs += in_buf_size;
2994
        if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user)))
2995
            break;
2996
        if (status != TINFL_STATUS_HAS_MORE_OUTPUT)
2997
        {
2998
            result = (status == TINFL_STATUS_DONE);
2999
            break;
3000
        }
3001
        dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1);
3002
    }
3003
    MZ_FREE(pDict);
3004
    *pIn_buf_size = in_buf_ofs;
3005
    return result;
3006
}
3007

3008
#ifndef MINIZ_NO_MALLOC
3009
tinfl_decompressor *tinfl_decompressor_alloc(void)
3010
{
3011
    tinfl_decompressor *pDecomp = (tinfl_decompressor *)MZ_MALLOC(sizeof(tinfl_decompressor));
3012
    if (pDecomp)
3013
        tinfl_init(pDecomp);
3014
    return pDecomp;
3015
}
3016

3017
void tinfl_decompressor_free(tinfl_decompressor *pDecomp)
3018
{
3019
    MZ_FREE(pDecomp);
3020
}
3021
#endif
3022

3023
#ifdef __cplusplus
3024
}
3025
#endif
3026
/**************************************************************************
3027
 *
3028
 * Copyright 2013-2014 RAD Game Tools and Valve Software
3029
 * Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
3030
 * Copyright 2016 Martin Raiber
3031
 * All Rights Reserved.
3032
 *
3033
 * Permission is hereby granted, free of charge, to any person obtaining a copy
3034
 * of this software and associated documentation files (the "Software"), to deal
3035
 * in the Software without restriction, including without limitation the rights
3036
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3037
 * copies of the Software, and to permit persons to whom the Software is
3038
 * furnished to do so, subject to the following conditions:
3039
 *
3040
 * The above copyright notice and this permission notice shall be included in
3041
 * all copies or substantial portions of the Software.
3042
 *
3043
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3044
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3045
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3046
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3047
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3048
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3049
 * THE SOFTWARE.
3050
 *
3051
 **************************************************************************/
3052

3053

3054
#ifndef MINIZ_NO_ARCHIVE_APIS
3055

3056
#ifdef __cplusplus
3057
extern "C" {
3058
#endif
3059

3060
/* ------------------- .ZIP archive reading */
3061

3062
#ifdef MINIZ_NO_STDIO
3063
#define MZ_FILE void *
3064
#else
3065
#include <sys/stat.h>
3066

3067
#if defined(_MSC_VER) || defined(__MINGW64__)
3068
static FILE *mz_fopen(const char *pFilename, const char *pMode)
3069
{
3070
    FILE *pFile = NULL;
3071
    fopen_s(&pFile, pFilename, pMode);
3072
    return pFile;
3073
}
3074
static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream)
3075
{
3076
    FILE *pFile = NULL;
3077
    if (freopen_s(&pFile, pPath, pMode, pStream))
3078
        return NULL;
3079
    return pFile;
3080
}
3081
#ifndef MINIZ_NO_TIME
3082
#include <sys/utime.h>
3083
#endif
3084
#define MZ_FOPEN mz_fopen
3085
#define MZ_FCLOSE fclose
3086
#define MZ_FREAD fread
3087
#define MZ_FWRITE fwrite
3088
#define MZ_FTELL64 _ftelli64
3089
#define MZ_FSEEK64 _fseeki64
3090
#define MZ_FILE_STAT_STRUCT _stat64
3091
#define MZ_FILE_STAT _stat64
3092
#define MZ_FFLUSH fflush
3093
#define MZ_FREOPEN mz_freopen
3094
#define MZ_DELETE_FILE remove
3095
#elif defined(__MINGW32__)
3096
#ifndef MINIZ_NO_TIME
3097
#include <sys/utime.h>
3098
#endif
3099
#define MZ_FOPEN(f, m) fopen(f, m)
3100
#define MZ_FCLOSE fclose
3101
#define MZ_FREAD fread
3102
#define MZ_FWRITE fwrite
3103
#define MZ_FTELL64 ftello64
3104
#define MZ_FSEEK64 fseeko64
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
#elif defined(__TINYC__)
3111
#ifndef MINIZ_NO_TIME
3112
#include <sys/utime.h>
3113
#endif
3114
#define MZ_FOPEN(f, m) fopen(f, m)
3115
#define MZ_FCLOSE fclose
3116
#define MZ_FREAD fread
3117
#define MZ_FWRITE fwrite
3118
#define MZ_FTELL64 ftell
3119
#define MZ_FSEEK64 fseek
3120
#define MZ_FILE_STAT_STRUCT stat
3121
#define MZ_FILE_STAT stat
3122
#define MZ_FFLUSH fflush
3123
#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3124
#define MZ_DELETE_FILE remove
3125
#elif defined(__GNUC__) && defined(_LARGEFILE64_SOURCE)
3126
#ifndef MINIZ_NO_TIME
3127
#include <utime.h>
3128
#endif
3129
#define MZ_FOPEN(f, m) fopen64(f, m)
3130
#define MZ_FCLOSE fclose
3131
#define MZ_FREAD fread
3132
#define MZ_FWRITE fwrite
3133
#define MZ_FTELL64 ftello64
3134
#define MZ_FSEEK64 fseeko64
3135
#define MZ_FILE_STAT_STRUCT stat64
3136
#define MZ_FILE_STAT stat64
3137
#define MZ_FFLUSH fflush
3138
#define MZ_FREOPEN(p, m, s) freopen64(p, m, s)
3139
#define MZ_DELETE_FILE remove
3140
#elif defined(__APPLE__)
3141
#ifndef MINIZ_NO_TIME
3142
#include <utime.h>
3143
#endif
3144
#define MZ_FOPEN(f, m) fopen(f, m)
3145
#define MZ_FCLOSE fclose
3146
#define MZ_FREAD fread
3147
#define MZ_FWRITE fwrite
3148
#define MZ_FTELL64 ftello
3149
#define MZ_FSEEK64 fseeko
3150
#define MZ_FILE_STAT_STRUCT stat
3151
#define MZ_FILE_STAT stat
3152
#define MZ_FFLUSH fflush
3153
#define MZ_FREOPEN(p, m, s) freopen(p, m, s)
3154
#define MZ_DELETE_FILE remove
3155

3156
#else
3157
#pragma message("Using fopen, ftello, fseeko, stat() etc. path for file I/O - this path may not support large files.")
3158
#ifndef MINIZ_NO_TIME
3159
#include <utime.h>
3160
#endif
3161
#define MZ_FOPEN(f, m) fopen(f, m)
3162
#define MZ_FCLOSE fclose
3163
#define MZ_FREAD fread
3164
#define MZ_FWRITE fwrite
3165
#ifdef __STRICT_ANSI__
3166
#define MZ_FTELL64 ftell
3167
#define MZ_FSEEK64 fseek
3168
#else
3169
#define MZ_FTELL64 ftello
3170
#define MZ_FSEEK64 fseeko
3171
#endif
3172
#define MZ_FILE_STAT_STRUCT stat
3173
#define MZ_FILE_STAT stat
3174
#define MZ_FFLUSH fflush
3175
#define MZ_FREOPEN(f, m, s) freopen(f, m, s)
3176
#define MZ_DELETE_FILE remove
3177
#endif /* #ifdef _MSC_VER */
3178
#endif /* #ifdef MINIZ_NO_STDIO */
3179

3180
#define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c))
3181

3182
/* 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. */
3183
enum
3184
{
3185
    /* ZIP archive identifiers and record sizes */
3186
    MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50,
3187
    MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50,
3188
    MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50,
3189
    MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30,
3190
    MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46,
3191
    MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22,
3192

3193
    /* ZIP64 archive identifier and record sizes */
3194
    MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06064b50,
3195
    MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG = 0x07064b50,
3196
    MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE = 56,
3197
    MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE = 20,
3198
    MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID = 0x0001,
3199
    MZ_ZIP_DATA_DESCRIPTOR_ID = 0x08074b50,
3200
    MZ_ZIP_DATA_DESCRIPTER_SIZE64 = 24,
3201
    MZ_ZIP_DATA_DESCRIPTER_SIZE32 = 16,
3202

3203
    /* Central directory header record offsets */
3204
    MZ_ZIP_CDH_SIG_OFS = 0,
3205
    MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4,
3206
    MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6,
3207
    MZ_ZIP_CDH_BIT_FLAG_OFS = 8,
3208
    MZ_ZIP_CDH_METHOD_OFS = 10,
3209
    MZ_ZIP_CDH_FILE_TIME_OFS = 12,
3210
    MZ_ZIP_CDH_FILE_DATE_OFS = 14,
3211
    MZ_ZIP_CDH_CRC32_OFS = 16,
3212
    MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20,
3213
    MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24,
3214
    MZ_ZIP_CDH_FILENAME_LEN_OFS = 28,
3215
    MZ_ZIP_CDH_EXTRA_LEN_OFS = 30,
3216
    MZ_ZIP_CDH_COMMENT_LEN_OFS = 32,
3217
    MZ_ZIP_CDH_DISK_START_OFS = 34,
3218
    MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36,
3219
    MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38,
3220
    MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42,
3221

3222
    /* Local directory header offsets */
3223
    MZ_ZIP_LDH_SIG_OFS = 0,
3224
    MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4,
3225
    MZ_ZIP_LDH_BIT_FLAG_OFS = 6,
3226
    MZ_ZIP_LDH_METHOD_OFS = 8,
3227
    MZ_ZIP_LDH_FILE_TIME_OFS = 10,
3228
    MZ_ZIP_LDH_FILE_DATE_OFS = 12,
3229
    MZ_ZIP_LDH_CRC32_OFS = 14,
3230
    MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18,
3231
    MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22,
3232
    MZ_ZIP_LDH_FILENAME_LEN_OFS = 26,
3233
    MZ_ZIP_LDH_EXTRA_LEN_OFS = 28,
3234
    MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR = 1 << 3,
3235

3236
    /* End of central directory offsets */
3237
    MZ_ZIP_ECDH_SIG_OFS = 0,
3238
    MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4,
3239
    MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6,
3240
    MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8,
3241
    MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10,
3242
    MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12,
3243
    MZ_ZIP_ECDH_CDIR_OFS_OFS = 16,
3244
    MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20,
3245

3246
    /* ZIP64 End of central directory locator offsets */
3247
    MZ_ZIP64_ECDL_SIG_OFS = 0,                    /* 4 bytes */
3248
    MZ_ZIP64_ECDL_NUM_DISK_CDIR_OFS = 4,          /* 4 bytes */
3249
    MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS = 8,  /* 8 bytes */
3250
    MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS = 16, /* 4 bytes */
3251

3252
    /* ZIP64 End of central directory header offsets */
3253
    MZ_ZIP64_ECDH_SIG_OFS = 0,                       /* 4 bytes */
3254
    MZ_ZIP64_ECDH_SIZE_OF_RECORD_OFS = 4,            /* 8 bytes */
3255
    MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS = 12,          /* 2 bytes */
3256
    MZ_ZIP64_ECDH_VERSION_NEEDED_OFS = 14,           /* 2 bytes */
3257
    MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS = 16,            /* 4 bytes */
3258
    MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS = 20,            /* 4 bytes */
3259
    MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 24, /* 8 bytes */
3260
    MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS = 32,       /* 8 bytes */
3261
    MZ_ZIP64_ECDH_CDIR_SIZE_OFS = 40,                /* 8 bytes */
3262
    MZ_ZIP64_ECDH_CDIR_OFS_OFS = 48,                 /* 8 bytes */
3263
    MZ_ZIP_VERSION_MADE_BY_DOS_FILESYSTEM_ID = 0,
3264
    MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG = 0x10,
3265
    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED = 1,
3266
    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG = 32,
3267
    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION = 64,
3268
    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED = 8192,
3269
    MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 = 1 << 11
3270
};
3271

3272
typedef struct
3273
{
3274
    void *m_p;
3275
    size_t m_size, m_capacity;
3276
    mz_uint m_element_size;
3277
} mz_zip_array;
3278

3279
struct mz_zip_internal_state_tag
3280
{
3281
    mz_zip_array m_central_dir;
3282
    mz_zip_array m_central_dir_offsets;
3283
    mz_zip_array m_sorted_central_dir_offsets;
3284

3285
    /* The flags passed in when the archive is initially opened. */
3286
    uint32_t m_init_flags;
3287

3288
    /* MZ_TRUE if the archive has a zip64 end of central directory headers, etc. */
3289
    mz_bool m_zip64;
3290

3291
    /* 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.) */
3292
    mz_bool m_zip64_has_extended_info_fields;
3293

3294
    /* These fields are used by the file, FILE, memory, and memory/heap read/write helpers. */
3295
    MZ_FILE *m_pFile;
3296
    mz_uint64 m_file_archive_start_ofs;
3297

3298
    void *m_pMem;
3299
    size_t m_mem_size;
3300
    size_t m_mem_capacity;
3301
};
3302

3303
#define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size
3304

3305
#if defined(DEBUG) || defined(_DEBUG) || defined(NDEBUG)
3306
static MZ_FORCEINLINE mz_uint mz_zip_array_range_check(const mz_zip_array *pArray, mz_uint index)
3307
{
3308
    MZ_ASSERT(index < pArray->m_size);
3309
    return index;
3310
}
3311
#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[mz_zip_array_range_check(array_ptr, index)]
3312
#else
3313
#define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index]
3314
#endif
3315

3316
static MZ_FORCEINLINE void mz_zip_array_init(mz_zip_array *pArray, mz_uint32 element_size)
3317
{
3318
    memset(pArray, 0, sizeof(mz_zip_array));
3319
    pArray->m_element_size = element_size;
3320
}
3321

3322
static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray)
3323
{
3324
    pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p);
3325
    memset(pArray, 0, sizeof(mz_zip_array));
3326
}
3327

3328
static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing)
3329
{
3330
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3331
    void *pNew_p;
3332
    size_t new_capacity = min_new_capacity;
3333
    MZ_ASSERT(pArray->m_element_size);
3334
    if (pArray->m_capacity >= min_new_capacity)
3335
        return MZ_TRUE;
3336
    if (growing)
3337
    {
3338
        new_capacity = MZ_MAX(1, pArray->m_capacity);
3339
        while (new_capacity < min_new_capacity)
3340
            new_capacity *= 2;
3341
    }
3342
    if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity)))
3343
        return MZ_FALSE;
3344
    pArray->m_p = pNew_p;
3345
    pArray->m_capacity = new_capacity;
3346
    return MZ_TRUE;
3347
}
3348

3349
static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing)
3350
{
3351
    if (new_capacity > pArray->m_capacity)
3352
    {
3353
        if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing))
3354
            return MZ_FALSE;
3355
    }
3356
    return MZ_TRUE;
3357
}
3358

3359
static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing)
3360
{
3361
    if (new_size > pArray->m_capacity)
3362
    {
3363
        if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing))
3364
            return MZ_FALSE;
3365
    }
3366
    pArray->m_size = new_size;
3367
    return MZ_TRUE;
3368
}
3369

3370
static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n)
3371
{
3372
    return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE);
3373
}
3374

3375
static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n)
3376
{
3377
    size_t orig_size = pArray->m_size;
3378
    if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE))
3379
        return MZ_FALSE;
3380
    if (n > 0)
3381
        memcpy((mz_uint8 *)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size);
3382
    return MZ_TRUE;
3383
}
3384

3385
#ifndef MINIZ_NO_TIME
3386
static MZ_TIME_T mz_zip_dos_to_time_t(int dos_time, int dos_date)
3387
{
3388
    struct tm tm;
3389
    memset(&tm, 0, sizeof(tm));
3390
    tm.tm_isdst = -1;
3391
    tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900;
3392
    tm.tm_mon = ((dos_date >> 5) & 15) - 1;
3393
    tm.tm_mday = dos_date & 31;
3394
    tm.tm_hour = (dos_time >> 11) & 31;
3395
    tm.tm_min = (dos_time >> 5) & 63;
3396
    tm.tm_sec = (dos_time << 1) & 62;
3397
    return mktime(&tm);
3398
}
3399

3400
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3401
static void mz_zip_time_t_to_dos_time(MZ_TIME_T time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date)
3402
{
3403
#ifdef _MSC_VER
3404
    struct tm tm_struct;
3405
    struct tm *tm = &tm_struct;
3406
    errno_t err = localtime_s(tm, &time);
3407
    if (err)
3408
    {
3409
        *pDOS_date = 0;
3410
        *pDOS_time = 0;
3411
        return;
3412
    }
3413
#else
3414
    struct tm *tm = localtime(&time);
3415
#endif /* #ifdef _MSC_VER */
3416

3417
    *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1));
3418
    *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday);
3419
}
3420
#endif /* MINIZ_NO_ARCHIVE_WRITING_APIS */
3421

3422
#ifndef MINIZ_NO_STDIO
3423
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
3424
static mz_bool mz_zip_get_file_modified_time(const char *pFilename, MZ_TIME_T *pTime)
3425
{
3426
    struct MZ_FILE_STAT_STRUCT file_stat;
3427

3428
    /* On Linux with x86 glibc, this call will fail on large files (I think >= 0x80000000 bytes) unless you compiled with _LARGEFILE64_SOURCE. Argh. */
3429
    if (MZ_FILE_STAT(pFilename, &file_stat) != 0)
3430
        return MZ_FALSE;
3431

3432
    *pTime = file_stat.st_mtime;
3433

3434
    return MZ_TRUE;
3435
}
3436
#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS*/
3437

3438
static mz_bool mz_zip_set_file_times(const char *pFilename, MZ_TIME_T access_time, MZ_TIME_T modified_time)
3439
{
3440
    struct utimbuf t;
3441

3442
    memset(&t, 0, sizeof(t));
3443
    t.actime = access_time;
3444
    t.modtime = modified_time;
3445

3446
    return !utime(pFilename, &t);
3447
}
3448
#endif /* #ifndef MINIZ_NO_STDIO */
3449
#endif /* #ifndef MINIZ_NO_TIME */
3450

3451
static MZ_FORCEINLINE mz_bool mz_zip_set_error(mz_zip_archive *pZip, mz_zip_error err_num)
3452
{
3453
    if (pZip)
3454
        pZip->m_last_error = err_num;
3455
    return MZ_FALSE;
3456
}
3457

3458
static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint flags)
3459
{
3460
    (void)flags;
3461
    if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
3462
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3463

3464
    if (!pZip->m_pAlloc)
3465
        pZip->m_pAlloc = miniz_def_alloc_func;
3466
    if (!pZip->m_pFree)
3467
        pZip->m_pFree = miniz_def_free_func;
3468
    if (!pZip->m_pRealloc)
3469
        pZip->m_pRealloc = miniz_def_realloc_func;
3470

3471
    pZip->m_archive_size = 0;
3472
    pZip->m_central_directory_file_ofs = 0;
3473
    pZip->m_total_files = 0;
3474
    pZip->m_last_error = MZ_ZIP_NO_ERROR;
3475

3476
    if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
3477
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3478

3479
    memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
3480
    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
3481
    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
3482
    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
3483
    pZip->m_pState->m_init_flags = flags;
3484
    pZip->m_pState->m_zip64 = MZ_FALSE;
3485
    pZip->m_pState->m_zip64_has_extended_info_fields = MZ_FALSE;
3486

3487
    pZip->m_zip_mode = MZ_ZIP_MODE_READING;
3488

3489
    return MZ_TRUE;
3490
}
3491

3492
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)
3493
{
3494
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3495
    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;
3496
    const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index));
3497
    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);
3498
    mz_uint8 l = 0, r = 0;
3499
    pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3500
    pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
3501
    pE = pL + MZ_MIN(l_len, r_len);
3502
    while (pL < pE)
3503
    {
3504
        if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
3505
            break;
3506
        pL++;
3507
        pR++;
3508
    }
3509
    return (pL == pE) ? (l_len < r_len) : (l < r);
3510
}
3511

3512
#define MZ_SWAP_UINT32(a, b) \
3513
    do                       \
3514
    {                        \
3515
        mz_uint32 t = a;     \
3516
        a = b;               \
3517
        b = t;               \
3518
    }                        \
3519
    MZ_MACRO_END
3520

3521
/* 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.) */
3522
static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip)
3523
{
3524
    mz_zip_internal_state *pState = pZip->m_pState;
3525
    const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
3526
    const mz_zip_array *pCentral_dir = &pState->m_central_dir;
3527
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3528
    mz_uint32 *pIndices;
3529
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3530
    mz_uint32 start, end;
3531
    const mz_uint32 size = pZip->m_total_files;
3532

3533
    if (size <= 1U)
3534
        return;
3535

3536
    pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
3537

3538
    start = (size - 2U) >> 1U;
3539
    for (;;)
3540
    {
3541
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3542
        mz_uint64 child, root = start;
3543
        for (;;)
3544
        {
3545
            if ((child = (root << 1U) + 1U) >= size)
3546
                break;
3547
            child += (((child + 1U) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U])));
3548
            if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3549
                break;
3550
            MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3551
            root = child;
3552
        }
3553
        if (!start)
3554
            break;
3555
        start--;
3556
    }
3557

3558
    end = size - 1;
3559
    while (end > 0)
3560
    {
3561
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3562
        mz_uint64 child, root = 0;
3563
        MZ_SWAP_UINT32(pIndices[end], pIndices[0]);
3564
        for (;;)
3565
        {
3566
            if ((child = (root << 1U) + 1U) >= end)
3567
                break;
3568
            child += (((child + 1U) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1U]));
3569
            if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child]))
3570
                break;
3571
            MZ_SWAP_UINT32(pIndices[root], pIndices[child]);
3572
            root = child;
3573
        }
3574
        end--;
3575
    }
3576
}
3577

3578
static mz_bool mz_zip_reader_locate_header_sig(mz_zip_archive *pZip, mz_uint32 record_sig, mz_uint32 record_size, mz_int64 *pOfs)
3579
{
3580
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3581
    mz_int64 cur_file_ofs;
3582
    mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3583
    mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3584

3585
    /* Basic sanity checks - reject files which are too small */
3586
    if (pZip->m_archive_size < record_size)
3587
        return MZ_FALSE;
3588

3589
    /* Find the record by scanning the file from the end towards the beginning. */
3590
    cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0);
3591
    for (;;)
3592
    {
3593
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3594
        int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs);
3595

3596
        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n)
3597
            return MZ_FALSE;
3598

3599
        for (i = n - 4; i >= 0; --i)
3600
        {
3601
            mz_uint s = MZ_READ_LE32(pBuf + i);
3602
            if (s == record_sig)
3603
            {
3604
                if ((pZip->m_archive_size - (cur_file_ofs + i)) >= record_size)
3605
                    break;
3606
            }
3607
        }
3608

3609
        if (i >= 0)
3610
        {
3611
            cur_file_ofs += i;
3612
            break;
3613
        }
3614

3615
        /* Give up if we've searched the entire file, or we've gone back "too far" (~64kb) */
3616
        if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (MZ_UINT16_MAX + record_size)))
3617
            return MZ_FALSE;
3618

3619
        cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0);
3620
    }
3621

3622
    *pOfs = cur_file_ofs;
3623
    return MZ_TRUE;
3624
}
3625

3626
static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint flags)
3627
{
3628
    mz_uint cdir_size = 0, cdir_entries_on_this_disk = 0, num_this_disk = 0, cdir_disk_index = 0;
3629
    mz_uint64 cdir_ofs = 0;
3630
    mz_int64 cur_file_ofs = 0;
3631
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3632
    const mz_uint8 *p;
3633

3634
    mz_uint32 buf_u32[4096 / sizeof(mz_uint32)];
3635
    mz_uint8 *pBuf = (mz_uint8 *)buf_u32;
3636
    mz_bool sort_central_dir = ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0);
3637
    mz_uint32 zip64_end_of_central_dir_locator_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3638
    mz_uint8 *pZip64_locator = (mz_uint8 *)zip64_end_of_central_dir_locator_u32;
3639

3640
    mz_uint32 zip64_end_of_central_dir_header_u32[(MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
3641
    mz_uint8 *pZip64_end_of_central_dir = (mz_uint8 *)zip64_end_of_central_dir_header_u32;
3642

3643
    mz_uint64 zip64_end_of_central_dir_ofs = 0;
3644

3645
    /* 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. */
3646
    if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3647
        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3648

3649
    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))
3650
        return mz_zip_set_error(pZip, MZ_ZIP_FAILED_FINDING_CENTRAL_DIR);
3651

3652
    /* Read and verify the end of central directory record. */
3653
    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)
3654
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3655

3656
    if (MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG)
3657
        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3658

3659
    if (cur_file_ofs >= (MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE + MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3660
    {
3661
        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)
3662
        {
3663
            if (MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG)
3664
            {
3665
                zip64_end_of_central_dir_ofs = MZ_READ_LE64(pZip64_locator + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS);
3666
                if (zip64_end_of_central_dir_ofs > (pZip->m_archive_size - MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE))
3667
                    return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3668

3669
                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)
3670
                {
3671
                    if (MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_SIG_OFS) == MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG)
3672
                    {
3673
                        pZip->m_pState->m_zip64 = MZ_TRUE;
3674
                    }
3675
                }
3676
            }
3677
        }
3678
    }
3679

3680
    pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3681
    cdir_entries_on_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS);
3682
    num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS);
3683
    cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS);
3684
    cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS);
3685
    cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS);
3686

3687
    if (pZip->m_pState->m_zip64)
3688
    {
3689
        // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
3690
        mz_uint32 zip64_total_num_of_disks = MZ_READ_LE32(pZip64_locator + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS);
3691
        // NOLINTNEXTLINE(clang-analyzer-core.UndefinedBinaryOperatorResult)
3692
        mz_uint64 zip64_cdir_total_entries = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS);
3693
        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);
3694
        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);
3695
        mz_uint64 zip64_size_of_central_directory = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_SIZE_OFS);
3696

3697
        if (zip64_size_of_end_of_central_dir_record < (MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE - 12))
3698
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3699

3700
        if (zip64_total_num_of_disks != 1U)
3701
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3702

3703
        /* Check for miniz's practical limits */
3704
        if (zip64_cdir_total_entries > MZ_UINT32_MAX)
3705
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3706

3707
        pZip->m_total_files = (mz_uint32)zip64_cdir_total_entries;
3708

3709
        if (zip64_cdir_total_entries_on_this_disk > MZ_UINT32_MAX)
3710
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
3711

3712
        cdir_entries_on_this_disk = (mz_uint32)zip64_cdir_total_entries_on_this_disk;
3713

3714
        /* Check for miniz's current practical limits (sorry, this should be enough for millions of files) */
3715
        if (zip64_size_of_central_directory > MZ_UINT32_MAX)
3716
            return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
3717

3718
        cdir_size = (mz_uint32)zip64_size_of_central_directory;
3719

3720
        num_this_disk = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_THIS_DISK_OFS);
3721

3722
        cdir_disk_index = MZ_READ_LE32(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_NUM_DISK_CDIR_OFS);
3723

3724
        cdir_ofs = MZ_READ_LE64(pZip64_end_of_central_dir + MZ_ZIP64_ECDH_CDIR_OFS_OFS);
3725
    }
3726

3727
    if (pZip->m_total_files != cdir_entries_on_this_disk)
3728
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3729

3730
    if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1)))
3731
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3732

3733
    if (cdir_size < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)
3734
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3735

3736
    if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size)
3737
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3738

3739
    pZip->m_central_directory_file_ofs = cdir_ofs;
3740

3741
    if (pZip->m_total_files)
3742
    {
3743
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3744
        mz_uint i, n;
3745
        /* 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. */
3746
        if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) ||
3747
            (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)))
3748
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3749

3750
        if (sort_central_dir)
3751
        {
3752
            if (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))
3753
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3754
        }
3755

3756
        if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size)
3757
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3758

3759
        /* Now create an index into the central directory file records, do some basic sanity checking on each record */
3760
        p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p;
3761
        for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i)
3762
        {
3763
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3764
            mz_uint total_header_size, disk_index, bit_flags, filename_size, ext_data_size;
3765
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3766
            mz_uint64 comp_size, decomp_size, local_header_ofs;
3767

3768
            if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG))
3769
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3770

3771
            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);
3772

3773
            if (sort_central_dir)
3774
                MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i;
3775

3776
            comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
3777
            decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
3778
            local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
3779
            filename_size = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
3780
            ext_data_size = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
3781

3782
            if ((!pZip->m_pState->m_zip64_has_extended_info_fields) &&
3783
                (ext_data_size) &&
3784
                (MZ_MAX(MZ_MAX(comp_size, decomp_size), local_header_ofs) == MZ_UINT32_MAX))
3785
            {
3786
                /* Attempt to find zip64 extended information field in the entry's extra data */
3787
                mz_uint32 extra_size_remaining = ext_data_size;
3788

3789
                if (extra_size_remaining)
3790
                {
3791
					const mz_uint8 *pExtra_data;
3792
					void* buf = NULL;
3793

3794
					if (MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + ext_data_size > n)
3795
					{
3796
						buf = MZ_MALLOC(ext_data_size);
3797
						if(buf==NULL)
3798
							return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
3799

3800
						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)
3801
						{
3802
							MZ_FREE(buf);
3803
							return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
3804
						}
3805

3806
						pExtra_data = (mz_uint8*)buf;
3807
					}
3808
					else
3809
					{
3810
						pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size;
3811
					}
3812

3813
                    do
3814
                    {
3815
                        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3816
                        mz_uint32 field_id;
3817
                        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
3818
                        mz_uint32 field_data_size;
3819

3820
						if (extra_size_remaining < (sizeof(mz_uint16) * 2))
3821
						{
3822
							MZ_FREE(buf);
3823
							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3824
						}
3825

3826
                        field_id = MZ_READ_LE16(pExtra_data);
3827
                        field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
3828

3829
						if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
3830
						{
3831
							MZ_FREE(buf);
3832
							return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3833
						}
3834

3835
                        if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
3836
                        {
3837
                            /* 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). */
3838
                            pZip->m_pState->m_zip64 = MZ_TRUE;
3839
                            pZip->m_pState->m_zip64_has_extended_info_fields = MZ_TRUE;
3840
                            break;
3841
                        }
3842

3843
                        pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
3844
                        extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
3845
                    } while (extra_size_remaining);
3846

3847
					MZ_FREE(buf);
3848
                }
3849
            }
3850

3851
            /* I've seen archives that aren't marked as zip64 that uses zip64 ext data, argh */
3852
            if ((comp_size != MZ_UINT32_MAX) && (decomp_size != MZ_UINT32_MAX))
3853
            {
3854
                if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size))
3855
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3856
            }
3857

3858
            disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS);
3859
            if ((disk_index == MZ_UINT16_MAX) || ((disk_index != num_this_disk) && (disk_index != 1)))
3860
                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_MULTIDISK);
3861

3862
            if (comp_size != MZ_UINT32_MAX)
3863
            {
3864
                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)
3865
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3866
            }
3867

3868
            bit_flags = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
3869
            if (bit_flags & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_LOCAL_DIR_IS_MASKED)
3870
                return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
3871

3872
            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)
3873
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
3874

3875
            n -= total_header_size;
3876
            p += total_header_size;
3877
        }
3878
    }
3879

3880
    if (sort_central_dir)
3881
        mz_zip_reader_sort_central_dir_offsets_by_filename(pZip);
3882

3883
    return MZ_TRUE;
3884
}
3885

3886
void mz_zip_zero_struct(mz_zip_archive *pZip)
3887
{
3888
    if (pZip)
3889
        MZ_CLEAR_OBJ(*pZip);
3890
}
3891

3892
static mz_bool mz_zip_reader_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
3893
{
3894
    mz_bool status = MZ_TRUE;
3895

3896
    if (!pZip)
3897
        return MZ_FALSE;
3898

3899
    if ((!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
3900
    {
3901
        if (set_last_error)
3902
            pZip->m_last_error = MZ_ZIP_INVALID_PARAMETER;
3903

3904
        return MZ_FALSE;
3905
    }
3906

3907
    if (pZip->m_pState)
3908
    {
3909
        mz_zip_internal_state *pState = pZip->m_pState;
3910
        pZip->m_pState = NULL;
3911

3912
        mz_zip_array_clear(pZip, &pState->m_central_dir);
3913
        mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
3914
        mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
3915

3916
#ifndef MINIZ_NO_STDIO
3917
        if (pState->m_pFile)
3918
        {
3919
            if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
3920
            {
3921
                if (MZ_FCLOSE(pState->m_pFile) == EOF)
3922
                {
3923
                    if (set_last_error)
3924
                        pZip->m_last_error = MZ_ZIP_FILE_CLOSE_FAILED;
3925
                    status = MZ_FALSE;
3926
                }
3927
            }
3928
            pState->m_pFile = NULL;
3929
        }
3930
#endif /* #ifndef MINIZ_NO_STDIO */
3931

3932
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
3933
    }
3934
    pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
3935

3936
    return status;
3937
}
3938

3939
mz_bool mz_zip_reader_end(mz_zip_archive *pZip)
3940
{
3941
    return mz_zip_reader_end_internal(pZip, MZ_TRUE);
3942
}
3943
mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags)
3944
{
3945
    if ((!pZip) || (!pZip->m_pRead))
3946
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3947

3948
    if (!mz_zip_reader_init_internal(pZip, flags))
3949
        return MZ_FALSE;
3950

3951
    pZip->m_zip_type = MZ_ZIP_TYPE_USER;
3952
    pZip->m_archive_size = size;
3953

3954
    if (!mz_zip_reader_read_central_dir(pZip, flags))
3955
    {
3956
        mz_zip_reader_end_internal(pZip, MZ_FALSE);
3957
        return MZ_FALSE;
3958
    }
3959

3960
    return MZ_TRUE;
3961
}
3962

3963
static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
3964
{
3965
    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
3966
    size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n);
3967
    memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s);
3968
    return s;
3969
}
3970

3971
mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags)
3972
{
3973
    if (!pMem)
3974
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
3975

3976
    if (size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
3977
        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
3978

3979
    if (!mz_zip_reader_init_internal(pZip, flags))
3980
        return MZ_FALSE;
3981

3982
    pZip->m_zip_type = MZ_ZIP_TYPE_MEMORY;
3983
    pZip->m_archive_size = size;
3984
    pZip->m_pRead = mz_zip_mem_read_func;
3985
    pZip->m_pIO_opaque = pZip;
3986
    pZip->m_pNeeds_keepalive = NULL;
3987

3988
#ifdef __cplusplus
3989
    pZip->m_pState->m_pMem = const_cast<void *>(pMem);
3990
#else
3991
    pZip->m_pState->m_pMem = (void *)pMem;
3992
#endif
3993

3994
    pZip->m_pState->m_mem_size = size;
3995

3996
    if (!mz_zip_reader_read_central_dir(pZip, flags))
3997
    {
3998
        mz_zip_reader_end_internal(pZip, MZ_FALSE);
3999
        return MZ_FALSE;
4000
    }
4001

4002
    return MZ_TRUE;
4003
}
4004

4005
#ifndef MINIZ_NO_STDIO
4006
static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
4007
{
4008
    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
4009
    mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
4010

4011
    file_ofs += pZip->m_pState->m_file_archive_start_ofs;
4012

4013
    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))))
4014
        return 0;
4015

4016
    return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile);
4017
}
4018

4019
mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags)
4020
{
4021
    return mz_zip_reader_init_file_v2(pZip, pFilename, flags, 0, 0);
4022
}
4023

4024
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)
4025
{
4026
    mz_uint64 file_size;
4027
    MZ_FILE *pFile;
4028

4029
    if ((!pZip) || (!pFilename) || ((archive_size) && (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)))
4030
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4031

4032
    pFile = MZ_FOPEN(pFilename, "rb");
4033
    if (!pFile)
4034
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4035

4036
    file_size = archive_size;
4037
    if (!file_size)
4038
    {
4039
        if (MZ_FSEEK64(pFile, 0, SEEK_END))
4040
        {
4041
            MZ_FCLOSE(pFile);
4042
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4043
        }
4044

4045
        file_size = MZ_FTELL64(pFile);
4046
    }
4047

4048
    /* TODO: Better sanity check archive_size and the # of actual remaining bytes */
4049

4050
    if (file_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4051
    {
4052
	MZ_FCLOSE(pFile);
4053
        return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4054
    }
4055

4056
    if (!mz_zip_reader_init_internal(pZip, flags))
4057
    {
4058
        MZ_FCLOSE(pFile);
4059
        return MZ_FALSE;
4060
    }
4061

4062
    pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
4063
    pZip->m_pRead = mz_zip_file_read_func;
4064
    pZip->m_pIO_opaque = pZip;
4065
    pZip->m_pState->m_pFile = pFile;
4066
    pZip->m_archive_size = file_size;
4067
    pZip->m_pState->m_file_archive_start_ofs = file_start_ofs;
4068

4069
    if (!mz_zip_reader_read_central_dir(pZip, flags))
4070
    {
4071
        mz_zip_reader_end_internal(pZip, MZ_FALSE);
4072
        return MZ_FALSE;
4073
    }
4074

4075
    return MZ_TRUE;
4076
}
4077

4078
mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags)
4079
{
4080
    mz_uint64 cur_file_ofs;
4081

4082
    if ((!pZip) || (!pFile))
4083
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
4084

4085
    cur_file_ofs = MZ_FTELL64(pFile);
4086

4087
    if (!archive_size)
4088
    {
4089
        if (MZ_FSEEK64(pFile, 0, SEEK_END))
4090
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
4091

4092
        archive_size = MZ_FTELL64(pFile) - cur_file_ofs;
4093

4094
        if (archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE)
4095
            return mz_zip_set_error(pZip, MZ_ZIP_NOT_AN_ARCHIVE);
4096
    }
4097

4098
    if (!mz_zip_reader_init_internal(pZip, flags))
4099
        return MZ_FALSE;
4100

4101
    pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
4102
    pZip->m_pRead = mz_zip_file_read_func;
4103

4104
    pZip->m_pIO_opaque = pZip;
4105
    pZip->m_pState->m_pFile = pFile;
4106
    pZip->m_archive_size = archive_size;
4107
    pZip->m_pState->m_file_archive_start_ofs = cur_file_ofs;
4108

4109
    if (!mz_zip_reader_read_central_dir(pZip, flags))
4110
    {
4111
        mz_zip_reader_end_internal(pZip, MZ_FALSE);
4112
        return MZ_FALSE;
4113
    }
4114

4115
    return MZ_TRUE;
4116
}
4117

4118
#endif /* #ifndef MINIZ_NO_STDIO */
4119

4120
static MZ_FORCEINLINE const mz_uint8 *mz_zip_get_cdh(mz_zip_archive *pZip, mz_uint file_index)
4121
{
4122
    if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files))
4123
        return NULL;
4124
    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));
4125
}
4126

4127
mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index)
4128
{
4129
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4130
    mz_uint m_bit_flag;
4131
    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4132
    if (!p)
4133
    {
4134
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4135
        return MZ_FALSE;
4136
    }
4137

4138
    m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4139
    return (m_bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION)) != 0;
4140
}
4141

4142
mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index)
4143
{
4144
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4145
    mz_uint bit_flag;
4146
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4147
    mz_uint method;
4148

4149
    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4150
    if (!p)
4151
    {
4152
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4153
        return MZ_FALSE;
4154
    }
4155

4156
    method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4157
    bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4158

4159
    if ((method != 0) && (method != MZ_DEFLATED))
4160
    {
4161
        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4162
        return MZ_FALSE;
4163
    }
4164

4165
    if (bit_flag & (MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_IS_ENCRYPTED | MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_USES_STRONG_ENCRYPTION))
4166
    {
4167
        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4168
        return MZ_FALSE;
4169
    }
4170

4171
    if (bit_flag & MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_COMPRESSED_PATCH_FLAG)
4172
    {
4173
        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
4174
        return MZ_FALSE;
4175
    }
4176

4177
    return MZ_TRUE;
4178
}
4179

4180
mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index)
4181
{
4182
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4183
    mz_uint filename_len, attribute_mapping_id, external_attr;
4184
    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4185
    if (!p)
4186
    {
4187
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4188
        return MZ_FALSE;
4189
    }
4190

4191
    filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4192
    if (filename_len)
4193
    {
4194
        if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/')
4195
            return MZ_TRUE;
4196
    }
4197

4198
    /* Bugfix: This code was also checking if the internal attribute was non-zero, which wasn't correct. */
4199
    /* 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. */
4200
    /* FIXME: Remove this check? Is it necessary - we already check the filename. */
4201
    attribute_mapping_id = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS) >> 8;
4202
    (void)attribute_mapping_id;
4203

4204
    external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4205
    if ((external_attr & MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG) != 0)
4206
    {
4207
        return MZ_TRUE;
4208
    }
4209

4210
    return MZ_FALSE;
4211
}
4212

4213
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)
4214
{
4215
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4216
    mz_uint n;
4217
    const mz_uint8 *p = pCentral_dir_header;
4218

4219
    if (pFound_zip64_extra_data)
4220
        *pFound_zip64_extra_data = MZ_FALSE;
4221

4222
    if ((!p) || (!pStat))
4223
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4224

4225
    /* Extract fields from the central directory record. */
4226
    pStat->m_file_index = file_index;
4227
    pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index);
4228
    pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS);
4229
    pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS);
4230
    pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS);
4231
    pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS);
4232
#ifndef MINIZ_NO_TIME
4233
    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));
4234
#endif
4235
    pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS);
4236
    pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4237
    pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4238
    pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS);
4239
    pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS);
4240
    pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS);
4241

4242
    /* Copy as much of the filename and comment as possible. */
4243
    n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4244
    n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1);
4245
    memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
4246
    pStat->m_filename[n] = '\0';
4247

4248
    n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS);
4249
    n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1);
4250
    pStat->m_comment_size = n;
4251
    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);
4252
    pStat->m_comment[n] = '\0';
4253

4254
    /* Set some flags for convienance */
4255
    pStat->m_is_directory = mz_zip_reader_is_file_a_directory(pZip, file_index);
4256
    pStat->m_is_encrypted = mz_zip_reader_is_file_encrypted(pZip, file_index);
4257
    pStat->m_is_supported = mz_zip_reader_is_file_supported(pZip, file_index);
4258

4259
    /* See if we need to read any zip64 extended information fields. */
4260
    /* 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). */
4261
    if (MZ_MAX(MZ_MAX(pStat->m_comp_size, pStat->m_uncomp_size), pStat->m_local_header_ofs) == MZ_UINT32_MAX)
4262
    {
4263
        /* Attempt to find zip64 extended information field in the entry's extra data */
4264
        mz_uint32 extra_size_remaining = MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS);
4265

4266
        if (extra_size_remaining)
4267
        {
4268
            const mz_uint8 *pExtra_data = p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4269

4270
            do
4271
            {
4272
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4273
                mz_uint32 field_id;
4274
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4275
                mz_uint32 field_data_size;
4276

4277
                if (extra_size_remaining < (sizeof(mz_uint16) * 2))
4278
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4279

4280
                field_id = MZ_READ_LE16(pExtra_data);
4281
                field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
4282

4283
                if ((field_data_size + sizeof(mz_uint16) * 2) > extra_size_remaining)
4284
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4285

4286
                if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
4287
                {
4288
                    const mz_uint8 *pField_data = pExtra_data + sizeof(mz_uint16) * 2;
4289
                    mz_uint32 field_data_remaining = field_data_size;
4290

4291
                    if (pFound_zip64_extra_data)
4292
                        *pFound_zip64_extra_data = MZ_TRUE;
4293

4294
                    if (pStat->m_uncomp_size == MZ_UINT32_MAX)
4295
                    {
4296
                        if (field_data_remaining < sizeof(mz_uint64))
4297
                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4298

4299
                        pStat->m_uncomp_size = MZ_READ_LE64(pField_data);
4300
                        pField_data += sizeof(mz_uint64);
4301
                        field_data_remaining -= sizeof(mz_uint64);
4302
                    }
4303

4304
                    if (pStat->m_comp_size == MZ_UINT32_MAX)
4305
                    {
4306
                        if (field_data_remaining < sizeof(mz_uint64))
4307
                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4308

4309
                        pStat->m_comp_size = MZ_READ_LE64(pField_data);
4310
                        pField_data += sizeof(mz_uint64);
4311
                        field_data_remaining -= sizeof(mz_uint64);
4312
                    }
4313

4314
                    if (pStat->m_local_header_ofs == MZ_UINT32_MAX)
4315
                    {
4316
                        if (field_data_remaining < sizeof(mz_uint64))
4317
                            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4318

4319
                        pStat->m_local_header_ofs = MZ_READ_LE64(pField_data);
4320
                        // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4321
                        pField_data += sizeof(mz_uint64);
4322
                        // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4323
                        field_data_remaining -= sizeof(mz_uint64);
4324
                    }
4325

4326
                    break;
4327
                }
4328

4329
                pExtra_data += sizeof(mz_uint16) * 2 + field_data_size;
4330
                extra_size_remaining = extra_size_remaining - sizeof(mz_uint16) * 2 - field_data_size;
4331
            } while (extra_size_remaining);
4332
        }
4333
    }
4334

4335
    return MZ_TRUE;
4336
}
4337

4338
static MZ_FORCEINLINE mz_bool mz_zip_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags)
4339
{
4340
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4341
    mz_uint i;
4342
    if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE)
4343
        return 0 == memcmp(pA, pB, len);
4344
    for (i = 0; i < len; ++i)
4345
        if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i]))
4346
            return MZ_FALSE;
4347
    return MZ_TRUE;
4348
}
4349

4350
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)
4351
{
4352
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4353
    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;
4354
    mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4355
    mz_uint8 l = 0, r = 0;
4356
    pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4357
    pE = pL + MZ_MIN(l_len, r_len);
4358
    while (pL < pE)
4359
    {
4360
        if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR)))
4361
            break;
4362
        pL++;
4363
        pR++;
4364
    }
4365
    return (pL == pE) ? (int)(l_len - r_len) : (l - r);
4366
}
4367

4368
static mz_bool mz_zip_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename, mz_uint32 *pIndex)
4369
{
4370
    mz_zip_internal_state *pState = pZip->m_pState;
4371
    const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets;
4372
    const mz_zip_array *pCentral_dir = &pState->m_central_dir;
4373
    mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0);
4374
    const uint32_t size = pZip->m_total_files;
4375
    const mz_uint filename_len = (mz_uint)strlen(pFilename);
4376

4377
    if (pIndex)
4378
        *pIndex = 0;
4379

4380
    if (size)
4381
    {
4382
        /* yes I could use uint32_t's, but then we would have to add some special case checks in the loop, argh, and */
4383
        /* honestly the major expense here on 32-bit CPU's will still be the filename compare */
4384
        mz_int64 l = 0, h = (mz_int64)size - 1;
4385

4386
        while (l <= h)
4387
        {
4388
            mz_int64 m = l + ((h - l) >> 1);
4389
            uint32_t file_index = pIndices[(uint32_t)m];
4390

4391
            int comp = mz_zip_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len);
4392
            if (!comp)
4393
            {
4394
                if (pIndex)
4395
                    *pIndex = file_index;
4396
                return MZ_TRUE;
4397
            }
4398
            else if (comp < 0)
4399
                l = m + 1;
4400
            else
4401
                h = m - 1;
4402
        }
4403
    }
4404

4405
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4406
}
4407

4408
int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags)
4409
{
4410
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4411
    mz_uint32 index;
4412
    if (!mz_zip_reader_locate_file_v2(pZip, pName, pComment, flags, &index))
4413
        return -1;
4414
    else
4415
        return (int)index;
4416
}
4417

4418
mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *pIndex)
4419
{
4420
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4421
    mz_uint file_index;
4422
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4423
    size_t name_len, comment_len;
4424

4425
    if (pIndex)
4426
        *pIndex = 0;
4427

4428
    if ((!pZip) || (!pZip->m_pState) || (!pName))
4429
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4430

4431
    /* See if we can use a binary search */
4432
    if (((pZip->m_pState->m_init_flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) &&
4433
        (pZip->m_zip_mode == MZ_ZIP_MODE_READING) &&
4434
        ((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_size))
4435
    {
4436
        return mz_zip_locate_file_binary_search(pZip, pName, pIndex);
4437
    }
4438

4439
    /* Locate the entry by scanning the entire central directory */
4440
    name_len = strlen(pName);
4441
    if (name_len > MZ_UINT16_MAX)
4442
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4443

4444
    comment_len = pComment ? strlen(pComment) : 0;
4445
    if (comment_len > MZ_UINT16_MAX)
4446
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4447

4448
    for (file_index = 0; file_index < pZip->m_total_files; file_index++)
4449
    {
4450
        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));
4451
        mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS);
4452
        const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE;
4453
        if (filename_len < name_len)
4454
            continue;
4455
        if (comment_len)
4456
        {
4457
            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);
4458
            const char *pFile_comment = pFilename + filename_len + file_extra_len;
4459
            if ((file_comment_len != comment_len) || (!mz_zip_string_equal(pComment, pFile_comment, file_comment_len, flags)))
4460
                continue;
4461
        }
4462
        if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len))
4463
        {
4464
            // NOLINTNEXTLINE(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions)
4465
            int ofs = filename_len - 1;
4466
            do
4467
            {
4468
                if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':'))
4469
                    break;
4470
            } while (--ofs >= 0);
4471
            ofs++;
4472
            pFilename += ofs;
4473
            filename_len -= ofs;
4474
        }
4475
        if ((filename_len == name_len) && (mz_zip_string_equal(pName, pFilename, filename_len, flags)))
4476
        {
4477
            if (pIndex)
4478
                *pIndex = file_index;
4479
            return MZ_TRUE;
4480
        }
4481
    }
4482

4483
    return mz_zip_set_error(pZip, MZ_ZIP_FILE_NOT_FOUND);
4484
}
4485

4486
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)
4487
{
4488
    int status = TINFL_STATUS_DONE;
4489
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4490
    mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail;
4491
    mz_zip_archive_file_stat file_stat;
4492
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4493
    void *pRead_buf;
4494
    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4495
    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4496
    tinfl_decompressor inflator;
4497

4498
    if ((!pZip) || (!pZip->m_pState) || ((buf_size) && (!pBuf)) || ((user_read_buf_size) && (!pUser_read_buf)) || (!pZip->m_pRead))
4499
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4500

4501
    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4502
        return MZ_FALSE;
4503

4504
    /* A directory or zero length file */
4505
    if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4506
        return MZ_TRUE;
4507

4508
    /* Encryption and patch files are not supported. */
4509
    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))
4510
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4511

4512
    /* This function only supports decompressing stored and deflate. */
4513
    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4514
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4515

4516
    /* Ensure supplied output buffer is large enough. */
4517
    needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size;
4518
    if (buf_size < needed_size)
4519
        return mz_zip_set_error(pZip, MZ_ZIP_BUF_TOO_SMALL);
4520

4521
    /* Read and parse the local directory entry. */
4522
    cur_file_ofs = file_stat.m_local_header_ofs;
4523
    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)
4524
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4525

4526
    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4527
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4528

4529
    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);
4530
    if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4531
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4532

4533
    if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4534
    {
4535
        /* The file is stored or the caller has requested the compressed data. */
4536
        if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size)
4537
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4538

4539
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4540
        if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) == 0)
4541
        {
4542
            if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4543
                return mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4544
        }
4545
#endif
4546

4547
        return MZ_TRUE;
4548
    }
4549

4550
    /* Decompress the file either directly from memory or from a file input buffer. */
4551
    tinfl_init(&inflator);
4552

4553
    if (pZip->m_pState->m_pMem)
4554
    {
4555
        /* Read directly from the archive in memory. */
4556
        pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4557
        read_buf_size = read_buf_avail = file_stat.m_comp_size;
4558
        comp_remaining = 0;
4559
    }
4560
    else if (pUser_read_buf)
4561
    {
4562
        /* Use a user provided read buffer. */
4563
        if (!user_read_buf_size)
4564
            return MZ_FALSE;
4565
        pRead_buf = (mz_uint8 *)pUser_read_buf;
4566
        read_buf_size = user_read_buf_size;
4567
        read_buf_avail = 0;
4568
        comp_remaining = file_stat.m_comp_size;
4569
    }
4570
    else
4571
    {
4572
        /* Temporarily allocate a read buffer. */
4573
        read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4574
        if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF))
4575
            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4576

4577
        if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4578
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4579

4580
        read_buf_avail = 0;
4581
        comp_remaining = file_stat.m_comp_size;
4582
    }
4583

4584
    do
4585
    {
4586
        /* The size_t cast here should be OK because we've verified that the output buffer is >= file_stat.m_uncomp_size above */
4587
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4588
        size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs);
4589
        if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4590
        {
4591
            read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4592
            if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4593
            {
4594
                status = TINFL_STATUS_FAILED;
4595
                mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4596
                break;
4597
            }
4598
            cur_file_ofs += read_buf_avail;
4599
            comp_remaining -= read_buf_avail;
4600
            read_buf_ofs = 0;
4601
        }
4602
        in_buf_size = (size_t)read_buf_avail;
4603
        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));
4604
        read_buf_avail -= in_buf_size;
4605
        read_buf_ofs += in_buf_size;
4606
        out_buf_ofs += out_buf_size;
4607
    } while (status == TINFL_STATUS_NEEDS_MORE_INPUT);
4608

4609
    if (status == TINFL_STATUS_DONE)
4610
    {
4611
        /* Make sure the entire file was decompressed, and check its CRC. */
4612
        if (out_buf_ofs != file_stat.m_uncomp_size)
4613
        {
4614
            mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4615
            status = TINFL_STATUS_FAILED;
4616
        }
4617
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4618
        else if (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)
4619
        {
4620
            mz_zip_set_error(pZip, MZ_ZIP_CRC_CHECK_FAILED);
4621
            status = TINFL_STATUS_FAILED;
4622
        }
4623
#endif
4624
    }
4625

4626
    if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf))
4627
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4628

4629
    return status == TINFL_STATUS_DONE;
4630
}
4631

4632
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)
4633
{
4634
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4635
    mz_uint32 file_index;
4636
    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4637
        return MZ_FALSE;
4638
    return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size);
4639
}
4640

4641
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)
4642
{
4643
    return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0);
4644
}
4645

4646
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)
4647
{
4648
    return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0);
4649
}
4650

4651
void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags)
4652
{
4653
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4654
    mz_uint64 comp_size, uncomp_size, alloc_size;
4655
    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
4656
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4657
    void *pBuf;
4658

4659
    if (pSize)
4660
        *pSize = 0;
4661

4662
    if (!p)
4663
    {
4664
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4665
        return NULL;
4666
    }
4667

4668
    comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS);
4669
    uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS);
4670

4671
    alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size;
4672
    if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF))
4673
    {
4674
        mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4675
        return NULL;
4676
    }
4677

4678
    if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size)))
4679
    {
4680
        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4681
        return NULL;
4682
    }
4683

4684
    if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags))
4685
    {
4686
        pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
4687
        return NULL;
4688
    }
4689

4690
    if (pSize)
4691
        *pSize = (size_t)alloc_size;
4692
    return pBuf;
4693
}
4694

4695
void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags)
4696
{
4697
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4698
    mz_uint32 file_index;
4699
    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4700
    {
4701
        if (pSize)
4702
            *pSize = 0;
4703
        return MZ_FALSE;
4704
    }
4705
    return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags);
4706
}
4707

4708
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)
4709
{
4710
    int status = TINFL_STATUS_DONE;
4711
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4712
    mz_uint file_crc32 = MZ_CRC32_INIT;
4713
#endif
4714
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4715
    mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs;
4716
    mz_zip_archive_file_stat file_stat;
4717
    void *pRead_buf = NULL;
4718
    void *pWrite_buf = NULL;
4719
    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4720
    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4721

4722
    if ((!pZip) || (!pZip->m_pState) || (!pCallback) || (!pZip->m_pRead))
4723
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
4724

4725
    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
4726
        return MZ_FALSE;
4727

4728
    /* A directory or zero length file */
4729
    if ((file_stat.m_is_directory) || (!file_stat.m_comp_size))
4730
        return MZ_TRUE;
4731

4732
    /* Encryption and patch files are not supported. */
4733
    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))
4734
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4735

4736
    /* This function only supports decompressing stored and deflate. */
4737
    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
4738
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4739

4740
    /* 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) */
4741
    cur_file_ofs = file_stat.m_local_header_ofs;
4742
    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)
4743
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4744

4745
    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4746
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4747

4748
    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);
4749
    if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size)
4750
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4751

4752
    /* Decompress the file either directly from memory or from a file input buffer. */
4753
    if (pZip->m_pState->m_pMem)
4754
    {
4755
        pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs;
4756
        read_buf_size = read_buf_avail = file_stat.m_comp_size;
4757
        comp_remaining = 0;
4758
    }
4759
    else
4760
    {
4761
        read_buf_size = MZ_MIN(file_stat.m_comp_size, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
4762
        if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size)))
4763
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4764

4765
        read_buf_avail = 0;
4766
        comp_remaining = file_stat.m_comp_size;
4767
    }
4768

4769
    if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method))
4770
    {
4771
        /* The file is stored or the caller has requested the compressed data. */
4772
        if (pZip->m_pState->m_pMem)
4773
        {
4774
            if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > MZ_UINT32_MAX))
4775
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
4776

4777
            if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size)
4778
            {
4779
                mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4780
                status = TINFL_STATUS_FAILED;
4781
            }
4782
            else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4783
            {
4784
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4785
                file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size);
4786
#endif
4787
            }
4788

4789
            // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4790
            cur_file_ofs += file_stat.m_comp_size;
4791
            out_buf_ofs += file_stat.m_comp_size;
4792
            // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
4793
            comp_remaining = 0;
4794
        }
4795
        else
4796
        {
4797
            while (comp_remaining)
4798
            {
4799
                read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4800
                if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4801
                {
4802
                    mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4803
                    status = TINFL_STATUS_FAILED;
4804
                    break;
4805
                }
4806

4807
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4808
                if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
4809
                {
4810
                    file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail);
4811
                }
4812
#endif
4813

4814
                if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4815
                {
4816
                    mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4817
                    status = TINFL_STATUS_FAILED;
4818
                    break;
4819
                }
4820

4821
                cur_file_ofs += read_buf_avail;
4822
                out_buf_ofs += read_buf_avail;
4823
                comp_remaining -= read_buf_avail;
4824
            }
4825
        }
4826
    }
4827
    else
4828
    {
4829
        tinfl_decompressor inflator;
4830
        tinfl_init(&inflator);
4831

4832
        if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
4833
        {
4834
            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4835
            status = TINFL_STATUS_FAILED;
4836
        }
4837
        else
4838
        {
4839
            do
4840
            {
4841
                mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4842
                // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4843
                size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
4844
                if ((!read_buf_avail) && (!pZip->m_pState->m_pMem))
4845
                {
4846
                    read_buf_avail = MZ_MIN(read_buf_size, comp_remaining);
4847
                    if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail)
4848
                    {
4849
                        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4850
                        status = TINFL_STATUS_FAILED;
4851
                        break;
4852
                    }
4853
                    cur_file_ofs += read_buf_avail;
4854
                    comp_remaining -= read_buf_avail;
4855
                    read_buf_ofs = 0;
4856
                }
4857

4858
                in_buf_size = (size_t)read_buf_avail;
4859
                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);
4860
                read_buf_avail -= in_buf_size;
4861
                read_buf_ofs += in_buf_size;
4862

4863
                if (out_buf_size)
4864
                {
4865
                    if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size)
4866
                    {
4867
                        mz_zip_set_error(pZip, MZ_ZIP_WRITE_CALLBACK_FAILED);
4868
                        status = TINFL_STATUS_FAILED;
4869
                        break;
4870
                    }
4871

4872
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4873
                    file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size);
4874
#endif
4875
                    if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size)
4876
                    {
4877
                        mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4878
                        status = TINFL_STATUS_FAILED;
4879
                        break;
4880
                    }
4881
                }
4882
            } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT));
4883
        }
4884
    }
4885

4886
    if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
4887
    {
4888
        /* Make sure the entire file was decompressed, and check its CRC. */
4889
        if (out_buf_ofs != file_stat.m_uncomp_size)
4890
        {
4891
            mz_zip_set_error(pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
4892
            status = TINFL_STATUS_FAILED;
4893
        }
4894
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4895
        else if (file_crc32 != file_stat.m_crc32)
4896
        {
4897
            mz_zip_set_error(pZip, MZ_ZIP_DECOMPRESSION_FAILED);
4898
            status = TINFL_STATUS_FAILED;
4899
        }
4900
#endif
4901
    }
4902

4903
    if (!pZip->m_pState->m_pMem)
4904
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
4905

4906
    if (pWrite_buf)
4907
        pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf);
4908

4909
    return status == TINFL_STATUS_DONE;
4910
}
4911

4912
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)
4913
{
4914
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4915
    mz_uint32 file_index;
4916
    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
4917
        return MZ_FALSE;
4918

4919
    return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags);
4920
}
4921

4922
mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
4923
{
4924
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
4925
    mz_zip_reader_extract_iter_state *pState;
4926
    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
4927
    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
4928

4929
    /* Argument sanity check */
4930
    if ((!pZip) || (!pZip->m_pState))
4931
        return NULL;
4932

4933
    /* Allocate an iterator status structure */
4934
    pState = (mz_zip_reader_extract_iter_state*)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_reader_extract_iter_state));
4935
    if (!pState)
4936
    {
4937
        mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
4938
        return NULL;
4939
    }
4940

4941
    /* Fetch file details */
4942
    if (!mz_zip_reader_file_stat(pZip, file_index, &pState->file_stat))
4943
    {
4944
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4945
        return NULL;
4946
    }
4947

4948
    /* Encryption and patch files are not supported. */
4949
    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))
4950
    {
4951
        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
4952
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4953
        return NULL;
4954
    }
4955

4956
    /* This function only supports decompressing stored and deflate. */
4957
    if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (pState->file_stat.m_method != 0) && (pState->file_stat.m_method != MZ_DEFLATED))
4958
    {
4959
        mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
4960
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4961
        return NULL;
4962
    }
4963

4964
    /* Init state - save args */
4965
    pState->pZip = pZip;
4966
    pState->flags = flags;
4967

4968
    /* Init state - reset variables to defaults */
4969
    pState->status = TINFL_STATUS_DONE;
4970
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
4971
    pState->file_crc32 = MZ_CRC32_INIT;
4972
#endif
4973
    pState->read_buf_ofs = 0;
4974
    pState->out_buf_ofs = 0;
4975
    pState->pRead_buf = NULL;
4976
    pState->pWrite_buf = NULL;
4977
    pState->out_blk_remain = 0;
4978

4979
    /* Read and parse the local directory entry. */
4980
    pState->cur_file_ofs = pState->file_stat.m_local_header_ofs;
4981
    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)
4982
    {
4983
        mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
4984
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4985
        return NULL;
4986
    }
4987

4988
    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
4989
    {
4990
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4991
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
4992
        return NULL;
4993
    }
4994

4995
    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);
4996
    if ((pState->cur_file_ofs + pState->file_stat.m_comp_size) > pZip->m_archive_size)
4997
    {
4998
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
4999
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5000
        return NULL;
5001
    }
5002

5003
    /* Decompress the file either directly from memory or from a file input buffer. */
5004
    if (pZip->m_pState->m_pMem)
5005
    {
5006
        pState->pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + pState->cur_file_ofs;
5007
        pState->read_buf_size = pState->read_buf_avail = pState->file_stat.m_comp_size;
5008
        pState->comp_remaining = pState->file_stat.m_comp_size;
5009
    }
5010
    else
5011
    {
5012
        if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5013
        {
5014
            /* Decompression required, therefore intermediate read buffer required */
5015
            pState->read_buf_size = MZ_MIN(pState->file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE);
5016
            if (NULL == (pState->pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)pState->read_buf_size)))
5017
            {
5018
                mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5019
                pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5020
                return NULL;
5021
            }
5022
        }
5023
        else
5024
        {
5025
            /* Decompression not required - we will be reading directly into user buffer, no temp buf required */
5026
            pState->read_buf_size = 0;
5027
        }
5028
        pState->read_buf_avail = 0;
5029
        pState->comp_remaining = pState->file_stat.m_comp_size;
5030
    }
5031

5032
    if (!((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method)))
5033
    {
5034
        /* Decompression required, init decompressor */
5035
        tinfl_init( &pState->inflator );
5036

5037
        /* Allocate write buffer */
5038
        if (NULL == (pState->pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE)))
5039
        {
5040
            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5041
            if (pState->pRead_buf)
5042
                pZip->m_pFree(pZip->m_pAlloc_opaque, pState->pRead_buf);
5043
            pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5044
            return NULL;
5045
        }
5046
    }
5047

5048
    return pState;
5049
}
5050

5051
mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
5052
{
5053
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5054
    mz_uint32 file_index;
5055

5056
    /* Locate file index by name */
5057
    if (!mz_zip_reader_locate_file_v2(pZip, pFilename, NULL, flags, &file_index))
5058
        return NULL;
5059

5060
    /* Construct iterator */
5061
    return mz_zip_reader_extract_iter_new(pZip, file_index, flags);
5062
}
5063

5064
size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size)
5065
{
5066
    size_t copied_to_caller = 0;
5067

5068
    /* Argument sanity check */
5069
    if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState) || (!pvBuf))
5070
        return 0;
5071

5072
    if ((pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!pState->file_stat.m_method))
5073
    {
5074
        /* The file is stored or the caller has requested the compressed data, calc amount to return. */
5075
        copied_to_caller = (size_t)MZ_MIN( buf_size, pState->comp_remaining );
5076

5077
        /* Zip is in memory....or requires reading from a file? */
5078
        if (pState->pZip->m_pState->m_pMem)
5079
        {
5080
            /* Copy data to caller's buffer */
5081
            memcpy( pvBuf, pState->pRead_buf, copied_to_caller );
5082
            pState->pRead_buf = ((mz_uint8*)pState->pRead_buf) + copied_to_caller;
5083
        }
5084
        else
5085
        {
5086
            /* Read directly into caller's buffer */
5087
            if (pState->pZip->m_pRead(pState->pZip->m_pIO_opaque, pState->cur_file_ofs, pvBuf, copied_to_caller) != copied_to_caller)
5088
            {
5089
                /* Failed to read all that was asked for, flag failure and alert user */
5090
                mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5091
                pState->status = TINFL_STATUS_FAILED;
5092
                copied_to_caller = 0;
5093
            }
5094
        }
5095

5096
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5097
        /* Compute CRC if not returning compressed data only */
5098
        if (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
5099
            pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, (const mz_uint8 *)pvBuf, copied_to_caller);
5100
#endif
5101

5102
        /* Advance offsets, dec counters */
5103
        pState->cur_file_ofs += copied_to_caller;
5104
        pState->out_buf_ofs += copied_to_caller;
5105
        pState->comp_remaining -= copied_to_caller;
5106
    }
5107
    else
5108
    {
5109
        do
5110
        {
5111
            /* Calc ptr to write buffer - given current output pos and block size */
5112
            mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pState->pWrite_buf + (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5113

5114
            /* Calc max output size - given current output pos and block size */
5115
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5116
            size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (pState->out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1));
5117

5118
            if (!pState->out_blk_remain)
5119
            {
5120
                /* Read more data from file if none available (and reading from file) */
5121
                if ((!pState->read_buf_avail) && (!pState->pZip->m_pState->m_pMem))
5122
                {
5123
                    /* Calc read size */
5124
                    pState->read_buf_avail = MZ_MIN(pState->read_buf_size, pState->comp_remaining);
5125
                    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)
5126
                    {
5127
                        mz_zip_set_error(pState->pZip, MZ_ZIP_FILE_READ_FAILED);
5128
                        pState->status = TINFL_STATUS_FAILED;
5129
                        break;
5130
                    }
5131

5132
                    /* Advance offsets, dec counters */
5133
                    pState->cur_file_ofs += pState->read_buf_avail;
5134
                    pState->comp_remaining -= pState->read_buf_avail;
5135
                    pState->read_buf_ofs = 0;
5136
                }
5137

5138
                /* Perform decompression */
5139
                in_buf_size = (size_t)pState->read_buf_avail;
5140
                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);
5141
                pState->read_buf_avail -= in_buf_size;
5142
                pState->read_buf_ofs += in_buf_size;
5143

5144
                /* Update current output block size remaining */
5145
                pState->out_blk_remain = out_buf_size;
5146
            }
5147

5148
            if (pState->out_blk_remain)
5149
            {
5150
                /* Calc amount to return. */
5151
                size_t to_copy = MZ_MIN( (buf_size - copied_to_caller), pState->out_blk_remain );
5152

5153
                /* Copy data to caller's buffer */
5154
                memcpy( (uint8_t*)pvBuf + copied_to_caller, pWrite_buf_cur, to_copy );
5155

5156
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5157
                /* Perform CRC */
5158
                pState->file_crc32 = (mz_uint32)mz_crc32(pState->file_crc32, pWrite_buf_cur, to_copy);
5159
#endif
5160

5161
                /* Decrement data consumed from block */
5162
                pState->out_blk_remain -= to_copy;
5163

5164
                /* Inc output offset, while performing sanity check */
5165
                if ((pState->out_buf_ofs += to_copy) > pState->file_stat.m_uncomp_size)
5166
                {
5167
                    mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5168
                    pState->status = TINFL_STATUS_FAILED;
5169
                    break;
5170
                }
5171

5172
                /* Increment counter of data copied to caller */
5173
                copied_to_caller += to_copy;
5174
            }
5175
        } while ( (copied_to_caller < buf_size) && ((pState->status == TINFL_STATUS_NEEDS_MORE_INPUT) || (pState->status == TINFL_STATUS_HAS_MORE_OUTPUT)) );
5176
    }
5177

5178
    /* Return how many bytes were copied into user buffer */
5179
    return copied_to_caller;
5180
}
5181

5182
mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState)
5183
{
5184
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5185
    int status;
5186

5187
    /* Argument sanity check */
5188
    if ((!pState) || (!pState->pZip) || (!pState->pZip->m_pState))
5189
        return MZ_FALSE;
5190

5191
    /* Was decompression completed and requested? */
5192
    if ((pState->status == TINFL_STATUS_DONE) && (!(pState->flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
5193
    {
5194
        /* Make sure the entire file was decompressed, and check its CRC. */
5195
        if (pState->out_buf_ofs != pState->file_stat.m_uncomp_size)
5196
        {
5197
            mz_zip_set_error(pState->pZip, MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE);
5198
            pState->status = TINFL_STATUS_FAILED;
5199
        }
5200
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
5201
        else if (pState->file_crc32 != pState->file_stat.m_crc32)
5202
        {
5203
            mz_zip_set_error(pState->pZip, MZ_ZIP_DECOMPRESSION_FAILED);
5204
            pState->status = TINFL_STATUS_FAILED;
5205
        }
5206
#endif
5207
    }
5208

5209
    /* Free buffers */
5210
    if (!pState->pZip->m_pState->m_pMem)
5211
        pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pRead_buf);
5212
    if (pState->pWrite_buf)
5213
        pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState->pWrite_buf);
5214

5215
    /* Save status */
5216
    status = pState->status;
5217

5218
    /* Free context */
5219
    pState->pZip->m_pFree(pState->pZip->m_pAlloc_opaque, pState);
5220

5221
    return status == TINFL_STATUS_DONE;
5222
}
5223

5224
#ifndef MINIZ_NO_STDIO
5225
static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n)
5226
{
5227
    (void)ofs;
5228

5229
    return MZ_FWRITE(pBuf, 1, n, (MZ_FILE *)pOpaque);
5230
}
5231

5232
mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags)
5233
{
5234
    mz_bool status;
5235
    mz_zip_archive_file_stat file_stat;
5236
    MZ_FILE *pFile;
5237

5238
    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5239
        return MZ_FALSE;
5240

5241
    if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5242
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5243

5244
    pFile = MZ_FOPEN(pDst_filename, "wb");
5245
    if (!pFile)
5246
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5247

5248
    status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5249

5250
    if (MZ_FCLOSE(pFile) == EOF)
5251
    {
5252
        if (status)
5253
            mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5254

5255
        status = MZ_FALSE;
5256
    }
5257

5258
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
5259
    if (status)
5260
        mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time);
5261
#endif
5262

5263
    return status;
5264
}
5265

5266
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags)
5267
{
5268
    mz_uint32 file_index;
5269
    if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5270
        return MZ_FALSE;
5271

5272
    return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags);
5273
}
5274

5275
mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *pFile, mz_uint flags)
5276
{
5277
    mz_zip_archive_file_stat file_stat;
5278

5279
    if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat))
5280
        return MZ_FALSE;
5281

5282
    if ((file_stat.m_is_directory) || (!file_stat.m_is_supported))
5283
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5284

5285
    return mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags);
5286
}
5287

5288
mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags)
5289
{
5290
    mz_uint32 file_index;
5291
    if (!mz_zip_reader_locate_file_v2(pZip, pArchive_filename, NULL, flags, &file_index))
5292
        return MZ_FALSE;
5293

5294
    return mz_zip_reader_extract_to_cfile(pZip, file_index, pFile, flags);
5295
}
5296
#endif /* #ifndef MINIZ_NO_STDIO */
5297

5298
static size_t mz_zip_compute_crc32_callback(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5299
{
5300
    mz_uint32 *p = (mz_uint32 *)pOpaque;
5301
    (void)file_ofs;
5302
    *p = (mz_uint32)mz_crc32(*p, (const mz_uint8 *)pBuf, n);
5303
    return n;
5304
}
5305

5306
mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags)
5307
{
5308
    mz_zip_archive_file_stat file_stat;
5309
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5310
    mz_zip_internal_state *pState;
5311
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5312
    const mz_uint8 *pCentral_dir_header;
5313
    mz_bool found_zip64_ext_data_in_cdir = MZ_FALSE;
5314
    mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
5315
    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
5316
    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
5317
    mz_uint64 local_header_ofs = 0;
5318
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5319
    mz_uint32 local_header_filename_len, local_header_extra_len, local_header_crc32;
5320
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5321
    mz_uint64 local_header_comp_size, local_header_uncomp_size;
5322
    mz_uint32 uncomp_crc32 = MZ_CRC32_INIT;
5323
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5324
    mz_bool has_data_descriptor;
5325
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5326
    mz_uint32 local_header_bit_flags;
5327

5328
    mz_zip_array file_data_array;
5329
    mz_zip_array_init(&file_data_array, 1);
5330

5331
    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5332
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5333

5334
    if (file_index > pZip->m_total_files)
5335
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5336

5337
    pState = pZip->m_pState;
5338

5339
    pCentral_dir_header = mz_zip_get_cdh(pZip, file_index);
5340

5341
    if (!mz_zip_file_stat_internal(pZip, file_index, pCentral_dir_header, &file_stat, &found_zip64_ext_data_in_cdir))
5342
        return MZ_FALSE;
5343

5344
    /* A directory or zero length file */
5345
    if ((file_stat.m_is_directory) || (!file_stat.m_uncomp_size))
5346
        return MZ_TRUE;
5347

5348
    /* Encryption and patch files are not supported. */
5349
    if (file_stat.m_is_encrypted)
5350
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_ENCRYPTION);
5351

5352
    /* This function only supports stored and deflate. */
5353
    if ((file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED))
5354
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_METHOD);
5355

5356
    if (!file_stat.m_is_supported)
5357
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_FEATURE);
5358

5359
    /* Read and parse the local directory entry. */
5360
    local_header_ofs = file_stat.m_local_header_ofs;
5361
    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)
5362
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5363

5364
    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
5365
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5366

5367
    local_header_filename_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
5368
    local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
5369
    local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
5370
    local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
5371
    local_header_crc32 = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_CRC32_OFS);
5372
    local_header_bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
5373
    has_data_descriptor = (local_header_bit_flags & 8) != 0;
5374

5375
    if (local_header_filename_len != strlen(file_stat.m_filename))
5376
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5377

5378
    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)
5379
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5380

5381
    if (!mz_zip_array_resize(pZip, &file_data_array, MZ_MAX(local_header_filename_len, local_header_extra_len), MZ_FALSE))
5382
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5383

5384
    if (local_header_filename_len)
5385
    {
5386
        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)
5387
        {
5388
            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5389
            goto handle_failure;
5390
        }
5391

5392
        /* 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. */
5393
        // NOLINTNEXTLINE(clang-analyzer-unix.cstring.NullArg)
5394
        if (memcmp(file_stat.m_filename, file_data_array.m_p, local_header_filename_len) != 0)
5395
        {
5396
            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5397
            goto handle_failure;
5398
        }
5399
    }
5400

5401
    if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
5402
    {
5403
        mz_uint32 extra_size_remaining = local_header_extra_len;
5404
        const mz_uint8 *pExtra_data = (const mz_uint8 *)file_data_array.m_p;
5405

5406
        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)
5407
        {
5408
            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5409
            goto handle_failure;
5410
        }
5411

5412
        do
5413
        {
5414
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5415
            mz_uint32 field_id, field_data_size, field_total_size;
5416

5417
            if (extra_size_remaining < (sizeof(mz_uint16) * 2))
5418
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5419

5420
            // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
5421
            field_id = MZ_READ_LE16(pExtra_data);
5422
            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
5423
            field_total_size = field_data_size + sizeof(mz_uint16) * 2;
5424

5425
            if (field_total_size > extra_size_remaining)
5426
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5427

5428
            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
5429
            {
5430
                const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
5431

5432
                if (field_data_size < sizeof(mz_uint64) * 2)
5433
                {
5434
                    mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
5435
                    goto handle_failure;
5436
                }
5437

5438
                local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
5439
                local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64));
5440

5441
                found_zip64_ext_data_in_ldir = MZ_TRUE;
5442
                break;
5443
            }
5444

5445
            pExtra_data += field_total_size;
5446
            extra_size_remaining -= field_total_size;
5447
        } while (extra_size_remaining);
5448
    }
5449

5450
    /* TODO: parse local header extra data when local_header_comp_size is 0xFFFFFFFF! (big_descriptor.zip) */
5451
    /* I've seen zips in the wild with the data descriptor bit set, but proper local header values and bogus data descriptors */
5452
    if ((has_data_descriptor) && (!local_header_comp_size) && (!local_header_crc32))
5453
    {
5454
        mz_uint8 descriptor_buf[32];
5455
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5456
        mz_bool has_id;
5457
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5458
        const mz_uint8 *pSrc;
5459
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5460
        mz_uint32 file_crc32;
5461
        mz_uint64 comp_size = 0, uncomp_size = 0;
5462

5463
        mz_uint32 num_descriptor_uint32s = ((pState->m_zip64) || (found_zip64_ext_data_in_ldir)) ? 6 : 4;
5464

5465
        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))
5466
        {
5467
            mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
5468
            goto handle_failure;
5469
        }
5470

5471
        has_id = (MZ_READ_LE32(descriptor_buf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
5472
        pSrc = has_id ? (descriptor_buf + sizeof(mz_uint32)) : descriptor_buf;
5473

5474
        file_crc32 = MZ_READ_LE32(pSrc);
5475

5476
        if ((pState->m_zip64) || (found_zip64_ext_data_in_ldir))
5477
        {
5478
            comp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32));
5479
            uncomp_size = MZ_READ_LE64(pSrc + sizeof(mz_uint32) + sizeof(mz_uint64));
5480
        }
5481
        else
5482
        {
5483
            comp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32));
5484
            uncomp_size = MZ_READ_LE32(pSrc + sizeof(mz_uint32) + sizeof(mz_uint32));
5485
        }
5486

5487
        if ((file_crc32 != file_stat.m_crc32) || (comp_size != file_stat.m_comp_size) || (uncomp_size != file_stat.m_uncomp_size))
5488
        {
5489
            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5490
            goto handle_failure;
5491
        }
5492
    }
5493
    else
5494
    {
5495
        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))
5496
        {
5497
            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5498
            goto handle_failure;
5499
        }
5500
    }
5501

5502
    mz_zip_array_clear(pZip, &file_data_array);
5503

5504
    if ((flags & MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY) == 0)
5505
    {
5506
        if (!mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_compute_crc32_callback, &uncomp_crc32, 0))
5507
            return MZ_FALSE;
5508

5509
        /* 1 more check to be sure, although the extract checks too. */
5510
        if (uncomp_crc32 != file_stat.m_crc32)
5511
        {
5512
            mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5513
            return MZ_FALSE;
5514
        }
5515
    }
5516

5517
    return MZ_TRUE;
5518

5519
handle_failure:
5520
    mz_zip_array_clear(pZip, &file_data_array);
5521
    return MZ_FALSE;
5522
}
5523

5524
mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags)
5525
{
5526
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5527
    mz_zip_internal_state *pState;
5528
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5529
    uint32_t i;
5530

5531
    if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (!pZip->m_pRead))
5532
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5533

5534
    pState = pZip->m_pState;
5535

5536
    /* Basic sanity checks */
5537
    if (!pState->m_zip64)
5538
    {
5539
        if (pZip->m_total_files > MZ_UINT16_MAX)
5540
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5541

5542
        if (pZip->m_archive_size > MZ_UINT32_MAX)
5543
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5544
    }
5545
    else
5546
    {
5547
        if (pZip->m_total_files >= MZ_UINT32_MAX)
5548
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5549

5550
        if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
5551
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
5552
    }
5553

5554
    for (i = 0; i < pZip->m_total_files; i++)
5555
    {
5556
        if (MZ_ZIP_FLAG_VALIDATE_LOCATE_FILE_FLAG & flags)
5557
        {
5558
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5559
            mz_uint32 found_index;
5560
            mz_zip_archive_file_stat stat;
5561

5562
            if (!mz_zip_reader_file_stat(pZip, i, &stat))
5563
                return MZ_FALSE;
5564

5565
            if (!mz_zip_reader_locate_file_v2(pZip, stat.m_filename, NULL, 0, &found_index))
5566
                return MZ_FALSE;
5567

5568
            /* 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) */
5569
            if (found_index != i)
5570
                return mz_zip_set_error(pZip, MZ_ZIP_VALIDATION_FAILED);
5571
        }
5572

5573
        if (!mz_zip_validate_file(pZip, i, flags))
5574
            return MZ_FALSE;
5575
    }
5576

5577
    return MZ_TRUE;
5578
}
5579

5580
mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr)
5581
{
5582
    mz_bool success = MZ_TRUE;
5583
    mz_zip_archive zip;
5584
    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5585

5586
    if ((!pMem) || (!size))
5587
    {
5588
        if (pErr)
5589
            *pErr = MZ_ZIP_INVALID_PARAMETER;
5590
        return MZ_FALSE;
5591
    }
5592

5593
    mz_zip_zero_struct(&zip);
5594

5595
    if (!mz_zip_reader_init_mem(&zip, pMem, size, flags))
5596
    {
5597
        if (pErr)
5598
            *pErr = zip.m_last_error;
5599
        return MZ_FALSE;
5600
    }
5601

5602
    if (!mz_zip_validate_archive(&zip, flags))
5603
    {
5604
        actual_err = zip.m_last_error;
5605
        success = MZ_FALSE;
5606
    }
5607

5608
    if (!mz_zip_reader_end_internal(&zip, success))
5609
    {
5610
        if (!actual_err)
5611
            actual_err = zip.m_last_error;
5612
        success = MZ_FALSE;
5613
    }
5614

5615
    if (pErr)
5616
        *pErr = actual_err;
5617

5618
    return success;
5619
}
5620

5621
#ifndef MINIZ_NO_STDIO
5622
mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr)
5623
{
5624
    mz_bool success = MZ_TRUE;
5625
    mz_zip_archive zip;
5626
    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
5627

5628
    if (!pFilename)
5629
    {
5630
        if (pErr)
5631
            *pErr = MZ_ZIP_INVALID_PARAMETER;
5632
        return MZ_FALSE;
5633
    }
5634

5635
    mz_zip_zero_struct(&zip);
5636

5637
    if (!mz_zip_reader_init_file_v2(&zip, pFilename, flags, 0, 0))
5638
    {
5639
        if (pErr)
5640
            *pErr = zip.m_last_error;
5641
        return MZ_FALSE;
5642
    }
5643

5644
    if (!mz_zip_validate_archive(&zip, flags))
5645
    {
5646
        actual_err = zip.m_last_error;
5647
        success = MZ_FALSE;
5648
    }
5649

5650
    if (!mz_zip_reader_end_internal(&zip, success))
5651
    {
5652
        if (!actual_err)
5653
            actual_err = zip.m_last_error;
5654
        success = MZ_FALSE;
5655
    }
5656

5657
    if (pErr)
5658
        *pErr = actual_err;
5659

5660
    return success;
5661
}
5662
#endif /* #ifndef MINIZ_NO_STDIO */
5663

5664
/* ------------------- .ZIP archive writing */
5665

5666
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
5667

5668
static MZ_FORCEINLINE void mz_write_le16(mz_uint8 *p, mz_uint16 v)
5669
{
5670
    p[0] = (mz_uint8)v;
5671
    p[1] = (mz_uint8)(v >> 8);
5672
}
5673
static MZ_FORCEINLINE void mz_write_le32(mz_uint8 *p, mz_uint32 v)
5674
{
5675
    p[0] = (mz_uint8)v;
5676
    p[1] = (mz_uint8)(v >> 8);
5677
    p[2] = (mz_uint8)(v >> 16);
5678
    p[3] = (mz_uint8)(v >> 24);
5679
}
5680
static MZ_FORCEINLINE void mz_write_le64(mz_uint8 *p, mz_uint64 v)
5681
{
5682
    mz_write_le32(p, (mz_uint32)v);
5683
    mz_write_le32(p + sizeof(mz_uint32), (mz_uint32)(v >> 32));
5684
}
5685

5686
#define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v))
5687
#define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v))
5688
#define MZ_WRITE_LE64(p, v) mz_write_le64((mz_uint8 *)(p), (mz_uint64)(v))
5689

5690
static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5691
{
5692
    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5693
    mz_zip_internal_state *pState = pZip->m_pState;
5694
    mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size);
5695

5696
    if (!n)
5697
        return 0;
5698

5699
    /* An allocation this big is likely to just fail on 32-bit systems, so don't even go there. */
5700
    if ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))
5701
    {
5702
        mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5703
        return 0;
5704
    }
5705

5706
    if (new_size > pState->m_mem_capacity)
5707
    {
5708
        // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5709
        void *pNew_block;
5710
        size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity);
5711

5712
        while (new_capacity < new_size)
5713
            new_capacity *= 2;
5714

5715
        if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity)))
5716
        {
5717
            mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5718
            return 0;
5719
        }
5720

5721
        pState->m_pMem = pNew_block;
5722
        pState->m_mem_capacity = new_capacity;
5723
    }
5724
    memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n);
5725
    pState->m_mem_size = (size_t)new_size;
5726
    return n;
5727
}
5728

5729
static mz_bool mz_zip_writer_end_internal(mz_zip_archive *pZip, mz_bool set_last_error)
5730
{
5731
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5732
    mz_zip_internal_state *pState;
5733
    mz_bool status = MZ_TRUE;
5734

5735
    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)))
5736
    {
5737
        if (set_last_error)
5738
            mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5739
        return MZ_FALSE;
5740
    }
5741

5742
    pState = pZip->m_pState;
5743
    pZip->m_pState = NULL;
5744
    mz_zip_array_clear(pZip, &pState->m_central_dir);
5745
    mz_zip_array_clear(pZip, &pState->m_central_dir_offsets);
5746
    mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets);
5747

5748
#ifndef MINIZ_NO_STDIO
5749
    if (pState->m_pFile)
5750
    {
5751
        if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5752
        {
5753
            if (MZ_FCLOSE(pState->m_pFile) == EOF)
5754
            {
5755
                if (set_last_error)
5756
                    mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
5757
                status = MZ_FALSE;
5758
            }
5759
        }
5760

5761
        pState->m_pFile = NULL;
5762
    }
5763
#endif /* #ifndef MINIZ_NO_STDIO */
5764

5765
    if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem))
5766
    {
5767
        pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem);
5768
        pState->m_pMem = NULL;
5769
    }
5770

5771
    pZip->m_pFree(pZip->m_pAlloc_opaque, pState);
5772
    pZip->m_zip_mode = MZ_ZIP_MODE_INVALID;
5773
    return status;
5774
}
5775

5776
mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags)
5777
{
5778
    mz_bool zip64 = (flags & MZ_ZIP_FLAG_WRITE_ZIP64) != 0;
5779

5780
    if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID))
5781
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5782

5783
    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5784
    {
5785
        if (!pZip->m_pRead)
5786
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5787
    }
5788

5789
    if (pZip->m_file_offset_alignment)
5790
    {
5791
        /* Ensure user specified file offset alignment is a power of 2. */
5792
        if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1))
5793
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5794
    }
5795

5796
    if (!pZip->m_pAlloc)
5797
        pZip->m_pAlloc = miniz_def_alloc_func;
5798
    if (!pZip->m_pFree)
5799
        pZip->m_pFree = miniz_def_free_func;
5800
    if (!pZip->m_pRealloc)
5801
        pZip->m_pRealloc = miniz_def_realloc_func;
5802

5803
    pZip->m_archive_size = existing_size;
5804
    pZip->m_central_directory_file_ofs = 0;
5805
    pZip->m_total_files = 0;
5806

5807
    if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state))))
5808
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5809

5810
    memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state));
5811

5812
    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8));
5813
    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32));
5814
    MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32));
5815

5816
    pZip->m_pState->m_zip64 = zip64;
5817
    pZip->m_pState->m_zip64_has_extended_info_fields = zip64;
5818

5819
    pZip->m_zip_type = MZ_ZIP_TYPE_USER;
5820
    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
5821

5822
    return MZ_TRUE;
5823
}
5824

5825
mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size)
5826
{
5827
    return mz_zip_writer_init_v2(pZip, existing_size, 0);
5828
}
5829

5830
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)
5831
{
5832
    pZip->m_pWrite = mz_zip_heap_write_func;
5833
    pZip->m_pNeeds_keepalive = NULL;
5834

5835
    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5836
        pZip->m_pRead = mz_zip_mem_read_func;
5837

5838
    pZip->m_pIO_opaque = pZip;
5839

5840
    if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5841
        return MZ_FALSE;
5842

5843
    pZip->m_zip_type = MZ_ZIP_TYPE_HEAP;
5844

5845
    if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning)))
5846
    {
5847
        if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size)))
5848
        {
5849
            mz_zip_writer_end_internal(pZip, MZ_FALSE);
5850
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
5851
        }
5852
        pZip->m_pState->m_mem_capacity = initial_allocation_size;
5853
    }
5854

5855
    return MZ_TRUE;
5856
}
5857

5858
mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size)
5859
{
5860
    return mz_zip_writer_init_heap_v2(pZip, size_to_reserve_at_beginning, initial_allocation_size, 0);
5861
}
5862

5863
#ifndef MINIZ_NO_STDIO
5864
static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n)
5865
{
5866
    mz_zip_archive *pZip = (mz_zip_archive *)pOpaque;
5867
    mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5868

5869
    file_ofs += pZip->m_pState->m_file_archive_start_ofs;
5870

5871
    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))))
5872
    {
5873
        mz_zip_set_error(pZip, MZ_ZIP_FILE_SEEK_FAILED);
5874
        return 0;
5875
    }
5876

5877
    return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile);
5878
}
5879

5880
mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning)
5881
{
5882
    return mz_zip_writer_init_file_v2(pZip, pFilename, size_to_reserve_at_beginning, 0);
5883
}
5884

5885
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)
5886
{
5887
    MZ_FILE *pFile;
5888

5889
    pZip->m_pWrite = mz_zip_file_write_func;
5890
    pZip->m_pNeeds_keepalive = NULL;
5891

5892
    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5893
        pZip->m_pRead = mz_zip_file_read_func;
5894

5895
    pZip->m_pIO_opaque = pZip;
5896

5897
    if (!mz_zip_writer_init_v2(pZip, size_to_reserve_at_beginning, flags))
5898
        return MZ_FALSE;
5899

5900
    if (NULL == (pFile = MZ_FOPEN(pFilename, (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING) ? "w+b" : "wb")))
5901
    {
5902
        mz_zip_writer_end(pZip);
5903
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
5904
    }
5905

5906
    pZip->m_pState->m_pFile = pFile;
5907
    pZip->m_zip_type = MZ_ZIP_TYPE_FILE;
5908

5909
    if (size_to_reserve_at_beginning)
5910
    {
5911
        mz_uint64 cur_ofs = 0;
5912
        char buf[4096];
5913

5914
        MZ_CLEAR_OBJ(buf);
5915

5916
        do
5917
        {
5918
            size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning);
5919
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n)
5920
            {
5921
                mz_zip_writer_end(pZip);
5922
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
5923
            }
5924
            cur_ofs += n;
5925
            size_to_reserve_at_beginning -= n;
5926
        } while (size_to_reserve_at_beginning);
5927
    }
5928

5929
    return MZ_TRUE;
5930
}
5931

5932
mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags)
5933
{
5934
    pZip->m_pWrite = mz_zip_file_write_func;
5935
    pZip->m_pNeeds_keepalive = NULL;
5936

5937
    if (flags & MZ_ZIP_FLAG_WRITE_ALLOW_READING)
5938
        pZip->m_pRead = mz_zip_file_read_func;
5939

5940
    pZip->m_pIO_opaque = pZip;
5941

5942
    if (!mz_zip_writer_init_v2(pZip, 0, flags))
5943
        return MZ_FALSE;
5944

5945
    pZip->m_pState->m_pFile = pFile;
5946
    pZip->m_pState->m_file_archive_start_ofs = MZ_FTELL64(pZip->m_pState->m_pFile);
5947
    pZip->m_zip_type = MZ_ZIP_TYPE_CFILE;
5948

5949
    return MZ_TRUE;
5950
}
5951
#endif /* #ifndef MINIZ_NO_STDIO */
5952

5953
mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags)
5954
{
5955
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
5956
    mz_zip_internal_state *pState;
5957

5958
    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING))
5959
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5960

5961
    if (flags & MZ_ZIP_FLAG_WRITE_ZIP64)
5962
    {
5963
        /* 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?) */
5964
        if (!pZip->m_pState->m_zip64)
5965
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5966
    }
5967

5968
    /* No sense in trying to write to an archive that's already at the support max size */
5969
    if (pZip->m_pState->m_zip64)
5970
    {
5971
        if (pZip->m_total_files == MZ_UINT32_MAX)
5972
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5973
    }
5974
    else
5975
    {
5976
        if (pZip->m_total_files == MZ_UINT16_MAX)
5977
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
5978

5979
        if ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > MZ_UINT32_MAX)
5980
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
5981
    }
5982

5983
    pState = pZip->m_pState;
5984

5985
    if (pState->m_pFile)
5986
    {
5987
#ifdef MINIZ_NO_STDIO
5988
        (void)pFilename;
5989
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5990
#else
5991
        if (pZip->m_pIO_opaque != pZip)
5992
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5993

5994
        if (pZip->m_zip_type == MZ_ZIP_TYPE_FILE)
5995
        {
5996
            if (!pFilename)
5997
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
5998

5999
            /* Archive is being read from stdio and was originally opened only for reading. Try to reopen as writable. */
6000
            if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile)))
6001
            {
6002
                /* The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. */
6003
                mz_zip_reader_end_internal(pZip, MZ_FALSE);
6004
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6005
            }
6006
        }
6007

6008
        pZip->m_pWrite = mz_zip_file_write_func;
6009
        pZip->m_pNeeds_keepalive = NULL;
6010
#endif /* #ifdef MINIZ_NO_STDIO */
6011
    }
6012
    else if (pState->m_pMem)
6013
    {
6014
        /* Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. */
6015
        if (pZip->m_pIO_opaque != pZip)
6016
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6017

6018
        pState->m_mem_capacity = pState->m_mem_size;
6019
        pZip->m_pWrite = mz_zip_heap_write_func;
6020
        pZip->m_pNeeds_keepalive = NULL;
6021
    }
6022
    /* Archive is being read via a user provided read function - make sure the user has specified a write function too. */
6023
    else if (!pZip->m_pWrite)
6024
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6025

6026
    /* Start writing new files at the archive's current central directory location. */
6027
    /* TODO: We could add a flag that lets the user start writing immediately AFTER the existing central dir - this would be safer. */
6028
    pZip->m_archive_size = pZip->m_central_directory_file_ofs;
6029
    pZip->m_central_directory_file_ofs = 0;
6030

6031
    /* Clear the sorted central dir offsets, they aren't useful or maintained now. */
6032
    /* Even though we're now in write mode, files can still be extracted and verified, but file locates will be slow. */
6033
    /* TODO: We could easily maintain the sorted central directory offsets. */
6034
    mz_zip_array_clear(pZip, &pZip->m_pState->m_sorted_central_dir_offsets);
6035

6036
    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING;
6037

6038
    return MZ_TRUE;
6039
}
6040

6041
mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename)
6042
{
6043
    return mz_zip_writer_init_from_reader_v2(pZip, pFilename, 0);
6044
}
6045

6046
/* TODO: pArchive_name is a terrible name here! */
6047
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)
6048
{
6049
    return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0);
6050
}
6051

6052
typedef struct
6053
{
6054
    mz_zip_archive *m_pZip;
6055
    mz_uint64 m_cur_archive_file_ofs;
6056
    mz_uint64 m_comp_size;
6057
} mz_zip_writer_add_state;
6058

6059
static mz_bool mz_zip_writer_add_put_buf_callback(const void *pBuf, int len, void *pUser)
6060
{
6061
    mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser;
6062
    if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len)
6063
        return MZ_FALSE;
6064

6065
    pState->m_cur_archive_file_ofs += len;
6066
    pState->m_comp_size += len;
6067
    return MZ_TRUE;
6068
}
6069

6070
#define MZ_ZIP64_MAX_LOCAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 2)
6071
#define MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE (sizeof(mz_uint16) * 2 + sizeof(mz_uint64) * 3)
6072
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)
6073
{
6074
    mz_uint8 *pDst = pBuf;
6075
    mz_uint32 field_size = 0;
6076

6077
    MZ_WRITE_LE16(pDst + 0, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6078
    MZ_WRITE_LE16(pDst + 2, 0);
6079
    pDst += sizeof(mz_uint16) * 2;
6080

6081
    if (pUncomp_size)
6082
    {
6083
        MZ_WRITE_LE64(pDst, *pUncomp_size);
6084
        pDst += sizeof(mz_uint64);
6085
        field_size += sizeof(mz_uint64);
6086
    }
6087

6088
    if (pComp_size)
6089
    {
6090
        MZ_WRITE_LE64(pDst, *pComp_size);
6091
        pDst += sizeof(mz_uint64);
6092
        field_size += sizeof(mz_uint64);
6093
    }
6094

6095
    if (pLocal_header_ofs)
6096
    {
6097
        MZ_WRITE_LE64(pDst, *pLocal_header_ofs);
6098
        pDst += sizeof(mz_uint64);
6099
        field_size += sizeof(mz_uint64);
6100
    }
6101

6102
    MZ_WRITE_LE16(pBuf + 2, field_size);
6103

6104
    return (mz_uint32)(pDst - pBuf);
6105
}
6106

6107
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)
6108
{
6109
    (void)pZip;
6110
    memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE);
6111
    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG);
6112
    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6113
    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags);
6114
    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method);
6115
    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time);
6116
    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date);
6117
    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32);
6118
    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6119
    MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6120
    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size);
6121
    MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size);
6122
    return MZ_TRUE;
6123
}
6124

6125
static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst,
6126
                                                       mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size,
6127
                                                       mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6128
                                                       mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6129
                                                       mz_uint64 local_header_ofs, mz_uint32 ext_attributes)
6130
{
6131
    (void)pZip;
6132
    memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
6133
    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG);
6134
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0);
6135
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags);
6136
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method);
6137
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time);
6138
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date);
6139
    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32);
6140
    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_MIN(comp_size, MZ_UINT32_MAX));
6141
    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_MIN(uncomp_size, MZ_UINT32_MAX));
6142
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size);
6143
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size);
6144
    MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size);
6145
    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes);
6146
    MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_MIN(local_header_ofs, MZ_UINT32_MAX));
6147
    return MZ_TRUE;
6148
}
6149

6150
static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size,
6151
                                                const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size,
6152
                                                mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32,
6153
                                                mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date,
6154
                                                mz_uint64 local_header_ofs, mz_uint32 ext_attributes,
6155
                                                const char *user_extra_data, mz_uint user_extra_data_len)
6156
{
6157
    mz_zip_internal_state *pState = pZip->m_pState;
6158
    mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size;
6159
    size_t orig_central_dir_size = pState->m_central_dir.m_size;
6160
    mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6161

6162
    if (!pZip->m_pState->m_zip64)
6163
    {
6164
        if (local_header_ofs > 0xFFFFFFFF)
6165
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_TOO_LARGE);
6166
    }
6167

6168
    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6169
    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)
6170
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6171

6172
    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))
6173
        return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6174

6175
    if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) ||
6176
        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) ||
6177
        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) ||
6178
        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, user_extra_data, user_extra_data_len)) ||
6179
        (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) ||
6180
        (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &central_dir_ofs, 1)))
6181
    {
6182
        /* Try to resize the central directory array back into its original state. */
6183
        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
6184
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6185
    }
6186

6187
    return MZ_TRUE;
6188
}
6189

6190
static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name)
6191
{
6192
    /* 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. */
6193
    if (*pArchive_name == '/')
6194
        return MZ_FALSE;
6195

6196
    /* Making sure the name does not contain drive letters or DOS style backward slashes is the responsibility of the program using miniz*/
6197

6198
    return MZ_TRUE;
6199
}
6200

6201
static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip)
6202
{
6203
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6204
    mz_uint32 n;
6205
    if (!pZip->m_file_offset_alignment)
6206
        return 0;
6207
    n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1));
6208
    return (mz_uint)((pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1));
6209
}
6210

6211
static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n)
6212
{
6213
    char buf[4096];
6214
    memset(buf, 0, MZ_MIN(sizeof(buf), n));
6215
    while (n)
6216
    {
6217
        mz_uint32 s = MZ_MIN(sizeof(buf), n);
6218
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s)
6219
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6220

6221
        cur_file_ofs += s;
6222
        n -= s;
6223
    }
6224
    return MZ_TRUE;
6225
}
6226

6227
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,
6228
                                 mz_uint64 uncomp_size, mz_uint32 uncomp_crc32)
6229
{
6230
    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);
6231
}
6232

6233
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,
6234
                                    mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified,
6235
                                    const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6236
{
6237
    mz_uint16 method = 0, dos_time = 0, dos_date = 0;
6238
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6239
    mz_uint level, ext_attributes = 0, num_alignment_padding_bytes;
6240
    mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0;
6241
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6242
    size_t archive_name_size;
6243
    mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6244
    tdefl_compressor *pComp = NULL;
6245
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6246
    mz_bool store_data_uncompressed;
6247
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6248
    mz_zip_internal_state *pState;
6249
    mz_uint8 *pExtra_data = NULL;
6250
    mz_uint32 extra_size = 0;
6251
    mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6252
    mz_uint16 bit_flags = 0;
6253
    mz_bool write_metadata_only = buf_size && !pBuf;
6254

6255
    if ((int)level_and_flags < 0)
6256
        level_and_flags = MZ_DEFAULT_LEVEL;
6257

6258
    if (uncomp_size || (buf_size && !(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)))
6259
        bit_flags |= MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6260

6261
    if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6262
        bit_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6263

6264
    level = level_and_flags & 0xF;
6265
    store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA));
6266

6267
    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6268
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6269

6270
    pState = pZip->m_pState;
6271

6272
    if (pState->m_zip64)
6273
    {
6274
        if (pZip->m_total_files == MZ_UINT32_MAX)
6275
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6276
    }
6277
    else
6278
    {
6279
        if (pZip->m_total_files == MZ_UINT16_MAX)
6280
        {
6281
            pState->m_zip64 = MZ_TRUE;
6282
            /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6283
        }
6284
        if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF))
6285
        {
6286
            pState->m_zip64 = MZ_TRUE;
6287
            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6288
        }
6289
    }
6290

6291
    if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size))
6292
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6293

6294
    if (!mz_zip_writer_validate_archive_name(pArchive_name))
6295
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6296

6297
#ifndef MINIZ_NO_TIME
6298
    if (last_modified != NULL)
6299
    {
6300
        mz_zip_time_t_to_dos_time(*last_modified, &dos_time, &dos_date);
6301
    }
6302
    else
6303
    {
6304
        MZ_TIME_T cur_time;
6305
        time(&cur_time);
6306
        mz_zip_time_t_to_dos_time(cur_time, &dos_time, &dos_date);
6307
    }
6308
#endif /* #ifndef MINIZ_NO_TIME */
6309

6310
	if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6311
	{
6312
        if (!write_metadata_only) {
6313
            uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, buf_size);
6314
        }
6315
		uncomp_size = buf_size;
6316
		if (uncomp_size <= 3)
6317
		{
6318
			level = 0;
6319
			store_data_uncompressed = MZ_TRUE;
6320
		}
6321
	}
6322

6323
    archive_name_size = strlen(pArchive_name);
6324
    if (archive_name_size > MZ_UINT16_MAX)
6325
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6326

6327
    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6328

6329
    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6330
    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)
6331
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6332

6333
    if (!pState->m_zip64)
6334
    {
6335
        /* Bail early if the archive would obviously become too large */
6336
        if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size
6337
			+ MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size + user_extra_data_len +
6338
			pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + user_extra_data_central_len
6339
			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32) > 0xFFFFFFFF)
6340
        {
6341
            pState->m_zip64 = MZ_TRUE;
6342
            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6343
        }
6344
    }
6345

6346
    if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/'))
6347
    {
6348
        /* Set DOS Subdirectory attribute bit. */
6349
        ext_attributes |= MZ_ZIP_DOS_DIR_ATTRIBUTE_BITFLAG;
6350

6351
        /* Subdirectories cannot contain data. */
6352
        if ((buf_size) || (uncomp_size))
6353
            return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6354
    }
6355

6356
    /* 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.) */
6357
    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)))
6358
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6359

6360
    if ((!store_data_uncompressed) && (buf_size))
6361
    {
6362
        if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor))))
6363
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6364
    }
6365

6366
    if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6367
    {
6368
        pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6369
        return MZ_FALSE;
6370
    }
6371

6372
    local_dir_header_ofs += num_alignment_padding_bytes;
6373
    if (pZip->m_file_offset_alignment)
6374
    {
6375
        MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6376
    }
6377
    cur_archive_file_ofs += num_alignment_padding_bytes;
6378

6379
    MZ_CLEAR_OBJ(local_dir_header);
6380

6381
    if (!store_data_uncompressed || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA))
6382
    {
6383
        method = MZ_DEFLATED;
6384
    }
6385

6386
    if (pState->m_zip64)
6387
    {
6388
        if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6389
        {
6390
            pExtra_data = extra_data;
6391
            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6392
                                                               (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6393
        }
6394

6395
        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))
6396
            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6397

6398
        if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6399
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6400

6401
        cur_archive_file_ofs += sizeof(local_dir_header);
6402

6403
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6404
        {
6405
            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6406
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6407
        }
6408
        cur_archive_file_ofs += archive_name_size;
6409

6410
        if (pExtra_data != NULL)
6411
        {
6412
            if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6413
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6414

6415
            cur_archive_file_ofs += extra_size;
6416
        }
6417
    }
6418
    else
6419
    {
6420
        if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6421
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6422
        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))
6423
            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6424

6425
        if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6426
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6427

6428
        cur_archive_file_ofs += sizeof(local_dir_header);
6429

6430
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6431
        {
6432
            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6433
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6434
        }
6435
        cur_archive_file_ofs += archive_name_size;
6436
    }
6437

6438
	if (user_extra_data_len > 0)
6439
	{
6440
		if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6441
			return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6442

6443
		cur_archive_file_ofs += user_extra_data_len;
6444
	}
6445

6446
    if (store_data_uncompressed)
6447
    {
6448
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size)
6449
        {
6450
            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6451
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6452
        }
6453

6454
        cur_archive_file_ofs += buf_size;
6455
        comp_size = buf_size;
6456
    }
6457
    else if (buf_size)
6458
    {
6459
        mz_zip_writer_add_state state;
6460

6461
        state.m_pZip = pZip;
6462
        state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6463
        state.m_comp_size = 0;
6464

6465
        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) ||
6466
            (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE))
6467
        {
6468
            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6469
            return mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6470
        }
6471

6472
        comp_size = state.m_comp_size;
6473
        cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6474
    }
6475

6476
    pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6477
    pComp = NULL;
6478

6479
    if (uncomp_size)
6480
    {
6481
        mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6482
        mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6483

6484
        MZ_ASSERT(bit_flags & MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR);
6485

6486
        MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6487
        MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6488
        if (pExtra_data == NULL)
6489
        {
6490
            if (comp_size > MZ_UINT32_MAX)
6491
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6492

6493
            MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6494
            MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6495
        }
6496
        else
6497
        {
6498
            MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6499
            MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6500
            local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6501
        }
6502

6503
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6504
            return MZ_FALSE;
6505

6506
        cur_archive_file_ofs += local_dir_footer_size;
6507
    }
6508

6509
    if (pExtra_data != NULL)
6510
    {
6511
        extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6512
                                                           (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6513
    }
6514

6515
    if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, pExtra_data, (mz_uint16)extra_size, pComment,
6516
                                          comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6517
                                          user_extra_data_central, user_extra_data_central_len))
6518
        return MZ_FALSE;
6519

6520
    pZip->m_total_files++;
6521
    pZip->m_archive_size = cur_archive_file_ofs;
6522

6523
    return MZ_TRUE;
6524
}
6525

6526
mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6527
                                const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6528
{
6529
    mz_uint16 gen_flags = MZ_ZIP_LDH_BIT_FLAG_HAS_LOCATOR;
6530
    mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes;
6531
    mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0;
6532
    mz_uint64 local_dir_header_ofs, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = size_to_add, comp_size = 0;
6533
    size_t archive_name_size;
6534
    mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE];
6535
    mz_uint8 *pExtra_data = NULL;
6536
    mz_uint32 extra_size = 0;
6537
    mz_uint8 extra_data[MZ_ZIP64_MAX_CENTRAL_EXTRA_FIELD_SIZE];
6538
    mz_zip_internal_state *pState;
6539
	mz_uint64 file_ofs = 0;
6540

6541
    if (!(level_and_flags & MZ_ZIP_FLAG_ASCII_FILENAME))
6542
        gen_flags |= MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8;
6543

6544
    if ((int)level_and_flags < 0)
6545
        level_and_flags = MZ_DEFAULT_LEVEL;
6546
    level = level_and_flags & 0xF;
6547

6548
    /* Sanity checks */
6549
    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION))
6550
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6551

6552
    pState = pZip->m_pState;
6553

6554
    if ((!pState->m_zip64) && (uncomp_size > MZ_UINT32_MAX))
6555
    {
6556
        /* Source file is too large for non-zip64 */
6557
        /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6558
        pState->m_zip64 = MZ_TRUE;
6559
    }
6560

6561
    /* We could support this, but why? */
6562
    if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)
6563
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6564

6565
    if (!mz_zip_writer_validate_archive_name(pArchive_name))
6566
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6567

6568
    if (pState->m_zip64)
6569
    {
6570
        if (pZip->m_total_files == MZ_UINT32_MAX)
6571
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
6572
    }
6573
    else
6574
    {
6575
        if (pZip->m_total_files == MZ_UINT16_MAX)
6576
        {
6577
            pState->m_zip64 = MZ_TRUE;
6578
            /*return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES); */
6579
        }
6580
    }
6581

6582
    archive_name_size = strlen(pArchive_name);
6583
    if (archive_name_size > MZ_UINT16_MAX)
6584
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_FILENAME);
6585

6586
    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
6587

6588
    /* miniz doesn't support central dirs >= MZ_UINT32_MAX bytes yet */
6589
    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)
6590
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
6591

6592
    if (!pState->m_zip64)
6593
    {
6594
        /* Bail early if the archive would obviously become too large */
6595
        if ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + archive_name_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE
6596
			+ archive_name_size + comment_size + user_extra_data_len + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE + 1024
6597
			+ MZ_ZIP_DATA_DESCRIPTER_SIZE32 + user_extra_data_central_len) > 0xFFFFFFFF)
6598
        {
6599
            pState->m_zip64 = MZ_TRUE;
6600
            /*return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE); */
6601
        }
6602
    }
6603

6604
#ifndef MINIZ_NO_TIME
6605
    if (pFile_time)
6606
    {
6607
        mz_zip_time_t_to_dos_time(*pFile_time, &dos_time, &dos_date);
6608
    }
6609
#endif
6610

6611
    if (uncomp_size <= 3)
6612
        level = 0;
6613

6614
    if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes))
6615
    {
6616
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6617
    }
6618

6619
    cur_archive_file_ofs += num_alignment_padding_bytes;
6620
    local_dir_header_ofs = cur_archive_file_ofs;
6621

6622
    if (pZip->m_file_offset_alignment)
6623
    {
6624
        MZ_ASSERT((cur_archive_file_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
6625
    }
6626

6627
    if (uncomp_size && level)
6628
    {
6629
        method = MZ_DEFLATED;
6630
    }
6631

6632
    MZ_CLEAR_OBJ(local_dir_header);
6633
    if (pState->m_zip64)
6634
    {
6635
        if (uncomp_size >= MZ_UINT32_MAX || local_dir_header_ofs >= MZ_UINT32_MAX)
6636
        {
6637
            pExtra_data = extra_data;
6638
            extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6639
                                                               (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6640
        }
6641

6642
        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))
6643
            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6644

6645
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6646
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6647

6648
        cur_archive_file_ofs += sizeof(local_dir_header);
6649

6650
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6651
        {
6652
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6653
        }
6654

6655
        cur_archive_file_ofs += archive_name_size;
6656

6657
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, extra_data, extra_size) != extra_size)
6658
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6659

6660
        cur_archive_file_ofs += extra_size;
6661
    }
6662
    else
6663
    {
6664
        if ((comp_size > MZ_UINT32_MAX) || (cur_archive_file_ofs > MZ_UINT32_MAX))
6665
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6666
        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))
6667
            return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6668

6669
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header))
6670
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6671

6672
        cur_archive_file_ofs += sizeof(local_dir_header);
6673

6674
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size)
6675
        {
6676
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6677
        }
6678

6679
        cur_archive_file_ofs += archive_name_size;
6680
    }
6681

6682
    if (user_extra_data_len > 0)
6683
    {
6684
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, user_extra_data, user_extra_data_len) != user_extra_data_len)
6685
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
6686

6687
        cur_archive_file_ofs += user_extra_data_len;
6688
    }
6689

6690
    if (uncomp_size)
6691
    {
6692
        mz_uint64 uncomp_remaining = uncomp_size;
6693
        void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE);
6694
        if (!pRead_buf)
6695
        {
6696
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6697
        }
6698

6699
        if (!level)
6700
        {
6701
            while (uncomp_remaining)
6702
            {
6703
                mz_uint n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining);
6704
                if ((read_callback(callback_opaque, file_ofs, pRead_buf, n) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n))
6705
                {
6706
                    pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6707
                    return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6708
                }
6709
				file_ofs += n;
6710
                uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n);
6711
                uncomp_remaining -= n;
6712
                cur_archive_file_ofs += n;
6713
            }
6714
            comp_size = uncomp_size;
6715
        }
6716
        else
6717
        {
6718
            mz_bool result = MZ_FALSE;
6719
            mz_zip_writer_add_state state;
6720
            tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor));
6721
            if (!pComp)
6722
            {
6723
                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6724
                return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6725
            }
6726

6727
            state.m_pZip = pZip;
6728
            state.m_cur_archive_file_ofs = cur_archive_file_ofs;
6729
            state.m_comp_size = 0;
6730

6731
            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)
6732
            {
6733
                pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6734
                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6735
                return mz_zip_set_error(pZip, MZ_ZIP_INTERNAL_ERROR);
6736
            }
6737

6738
            for (;;)
6739
            {
6740
                size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, (mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE);
6741
                tdefl_status status;
6742
                tdefl_flush flush = TDEFL_NO_FLUSH;
6743

6744
                if (read_callback(callback_opaque, file_ofs, pRead_buf, in_buf_size)!= in_buf_size)
6745
                {
6746
                    mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
6747
                    break;
6748
                }
6749

6750
				file_ofs += in_buf_size;
6751
                uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size);
6752
                uncomp_remaining -= in_buf_size;
6753

6754
                if (pZip->m_pNeeds_keepalive != NULL && pZip->m_pNeeds_keepalive(pZip->m_pIO_opaque))
6755
                    flush = TDEFL_FULL_FLUSH;
6756

6757
                status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? flush : TDEFL_FINISH);
6758
                if (status == TDEFL_STATUS_DONE)
6759
                {
6760
                    result = MZ_TRUE;
6761
                    break;
6762
                }
6763
                else if (status != TDEFL_STATUS_OKAY)
6764
                {
6765
                    mz_zip_set_error(pZip, MZ_ZIP_COMPRESSION_FAILED);
6766
                    break;
6767
                }
6768
            }
6769

6770
            pZip->m_pFree(pZip->m_pAlloc_opaque, pComp);
6771

6772
            if (!result)
6773
            {
6774
                pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6775
                return MZ_FALSE;
6776
            }
6777

6778
            comp_size = state.m_comp_size;
6779
            cur_archive_file_ofs = state.m_cur_archive_file_ofs;
6780
        }
6781

6782
        pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf);
6783
    }
6784

6785
    {
6786
        mz_uint8 local_dir_footer[MZ_ZIP_DATA_DESCRIPTER_SIZE64];
6787
        mz_uint32 local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE32;
6788

6789
        MZ_WRITE_LE32(local_dir_footer + 0, MZ_ZIP_DATA_DESCRIPTOR_ID);
6790
        MZ_WRITE_LE32(local_dir_footer + 4, uncomp_crc32);
6791
        if (pExtra_data == NULL)
6792
        {
6793
            if (comp_size > MZ_UINT32_MAX)
6794
                return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
6795

6796
            MZ_WRITE_LE32(local_dir_footer + 8, comp_size);
6797
            MZ_WRITE_LE32(local_dir_footer + 12, uncomp_size);
6798
        }
6799
        else
6800
        {
6801
            MZ_WRITE_LE64(local_dir_footer + 8, comp_size);
6802
            MZ_WRITE_LE64(local_dir_footer + 16, uncomp_size);
6803
            local_dir_footer_size = MZ_ZIP_DATA_DESCRIPTER_SIZE64;
6804
        }
6805

6806
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, local_dir_footer, local_dir_footer_size) != local_dir_footer_size)
6807
            return MZ_FALSE;
6808

6809
        cur_archive_file_ofs += local_dir_footer_size;
6810
    }
6811

6812
    if (pExtra_data != NULL)
6813
    {
6814
        extra_size = mz_zip_writer_create_zip64_extra_data(extra_data, (uncomp_size >= MZ_UINT32_MAX) ? &uncomp_size : NULL,
6815
                                                           (uncomp_size >= MZ_UINT32_MAX) ? &comp_size : NULL, (local_dir_header_ofs >= MZ_UINT32_MAX) ? &local_dir_header_ofs : NULL);
6816
    }
6817

6818
    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,
6819
                                          uncomp_size, comp_size, uncomp_crc32, method, gen_flags, dos_time, dos_date, local_dir_header_ofs, ext_attributes,
6820
                                          user_extra_data_central, user_extra_data_central_len))
6821
        return MZ_FALSE;
6822

6823
    pZip->m_total_files++;
6824
    pZip->m_archive_size = cur_archive_file_ofs;
6825

6826
    return MZ_TRUE;
6827
}
6828

6829
#ifndef MINIZ_NO_STDIO
6830

6831
static size_t mz_file_read_func_stdio(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n)
6832
{
6833
	MZ_FILE *pSrc_file = (MZ_FILE *)pOpaque;
6834
	mz_int64 cur_ofs = MZ_FTELL64(pSrc_file);
6835

6836
	if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pSrc_file, (mz_int64)file_ofs, SEEK_SET))))
6837
		return 0;
6838

6839
	return MZ_FREAD(pBuf, 1, n, pSrc_file);
6840
}
6841

6842
mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add, const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
6843
	const char *user_extra_data, mz_uint user_extra_data_len, const char *user_extra_data_central, mz_uint user_extra_data_central_len)
6844
{
6845
	return mz_zip_writer_add_read_buf_callback(pZip, pArchive_name, mz_file_read_func_stdio, pSrc_file, size_to_add, pFile_time, pComment, comment_size, level_and_flags,
6846
		user_extra_data, user_extra_data_len, user_extra_data_central, user_extra_data_central_len);
6847
}
6848

6849
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)
6850
{
6851
    MZ_FILE *pSrc_file = NULL;
6852
    mz_uint64 uncomp_size = 0;
6853
    MZ_TIME_T file_modified_time;
6854
    MZ_TIME_T *pFile_time = NULL;
6855
    mz_bool status;
6856

6857
    memset(&file_modified_time, 0, sizeof(file_modified_time));
6858

6859
#if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_STDIO)
6860
    pFile_time = &file_modified_time;
6861
    if (!mz_zip_get_file_modified_time(pSrc_filename, &file_modified_time))
6862
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_STAT_FAILED);
6863
#endif
6864

6865
    pSrc_file = MZ_FOPEN(pSrc_filename, "rb");
6866
    if (!pSrc_file)
6867
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_OPEN_FAILED);
6868

6869
    MZ_FSEEK64(pSrc_file, 0, SEEK_END);
6870
    uncomp_size = MZ_FTELL64(pSrc_file);
6871
    MZ_FSEEK64(pSrc_file, 0, SEEK_SET);
6872

6873
    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);
6874

6875
    MZ_FCLOSE(pSrc_file);
6876

6877
    return status;
6878
}
6879
#endif /* #ifndef MINIZ_NO_STDIO */
6880

6881
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)
6882
{
6883
    /* + 64 should be enough for any new zip64 data */
6884
    if (!mz_zip_array_reserve(pZip, pNew_ext, ext_len + 64, MZ_FALSE))
6885
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6886

6887
    mz_zip_array_resize(pZip, pNew_ext, 0, MZ_FALSE);
6888

6889
    if ((pUncomp_size) || (pComp_size) || (pLocal_header_ofs) || (pDisk_start))
6890
    {
6891
        mz_uint8 new_ext_block[64];
6892
        mz_uint8 *pDst = new_ext_block;
6893
        mz_write_le16(pDst, MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID);
6894
        mz_write_le16(pDst + sizeof(mz_uint16), 0);
6895
        pDst += sizeof(mz_uint16) * 2;
6896

6897
        if (pUncomp_size)
6898
        {
6899
            mz_write_le64(pDst, *pUncomp_size);
6900
            pDst += sizeof(mz_uint64);
6901
        }
6902

6903
        if (pComp_size)
6904
        {
6905
            mz_write_le64(pDst, *pComp_size);
6906
            pDst += sizeof(mz_uint64);
6907
        }
6908

6909
        if (pLocal_header_ofs)
6910
        {
6911
            mz_write_le64(pDst, *pLocal_header_ofs);
6912
            pDst += sizeof(mz_uint64);
6913
        }
6914

6915
        if (pDisk_start)
6916
        {
6917
            mz_write_le32(pDst, *pDisk_start);
6918
            pDst += sizeof(mz_uint32);
6919
        }
6920

6921
        mz_write_le16(new_ext_block + sizeof(mz_uint16), (mz_uint16)((pDst - new_ext_block) - sizeof(mz_uint16) * 2));
6922

6923
        if (!mz_zip_array_push_back(pZip, pNew_ext, new_ext_block, pDst - new_ext_block))
6924
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6925
    }
6926

6927
    if ((pExt) && (ext_len))
6928
    {
6929
        mz_uint32 extra_size_remaining = ext_len;
6930
        const mz_uint8 *pExtra_data = pExt;
6931

6932
        do
6933
        {
6934
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6935
            mz_uint32 field_id, field_data_size, field_total_size;
6936

6937
            if (extra_size_remaining < (sizeof(mz_uint16) * 2))
6938
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6939

6940
            field_id = MZ_READ_LE16(pExtra_data);
6941
            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
6942
            field_total_size = field_data_size + sizeof(mz_uint16) * 2;
6943

6944
            if (field_total_size > extra_size_remaining)
6945
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
6946

6947
            if (field_id != MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
6948
            {
6949
                if (!mz_zip_array_push_back(pZip, pNew_ext, pExtra_data, field_total_size))
6950
                    return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
6951
            }
6952

6953
            pExtra_data += field_total_size;
6954
            extra_size_remaining -= field_total_size;
6955
        } while (extra_size_remaining);
6956
    }
6957

6958
    return MZ_TRUE;
6959
}
6960

6961
/* TODO: This func is now pretty freakin complex due to zip64, split it up? */
6962
mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index)
6963
{
6964
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6965
    mz_uint n, bit_flags, num_alignment_padding_bytes, src_central_dir_following_data_size;
6966
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6967
    mz_uint64 src_archive_bytes_remaining, local_dir_header_ofs;
6968
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6969
    mz_uint64 cur_src_file_ofs, cur_dst_file_ofs;
6970
    mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)];
6971
    mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32;
6972
    mz_uint8 new_central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE];
6973
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6974
    size_t orig_central_dir_size;
6975
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6976
    mz_zip_internal_state *pState;
6977
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6978
    void *pBuf;
6979
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6980
    const mz_uint8 *pSrc_central_header;
6981
    mz_zip_archive_file_stat src_file_stat;
6982
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6983
    mz_uint32 src_filename_len, src_comment_len, src_ext_len;
6984
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6985
    mz_uint32 local_header_filename_size, local_header_extra_len;
6986
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
6987
    mz_uint64 local_header_comp_size, local_header_uncomp_size;
6988
    mz_bool found_zip64_ext_data_in_ldir = MZ_FALSE;
6989

6990
    /* Sanity checks */
6991
    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pSource_zip->m_pRead))
6992
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6993

6994
    pState = pZip->m_pState;
6995

6996
    /* Don't support copying files from zip64 archives to non-zip64, even though in some cases this is possible */
6997
    if ((pSource_zip->m_pState->m_zip64) && (!pZip->m_pState->m_zip64))
6998
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
6999

7000
    /* Get pointer to the source central dir header and crack it */
7001
    if (NULL == (pSrc_central_header = mz_zip_get_cdh(pSource_zip, src_file_index)))
7002
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7003

7004
    if (MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_SIG_OFS) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)
7005
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7006

7007
    src_filename_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7008
    src_comment_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS);
7009
    src_ext_len = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS);
7010
    src_central_dir_following_data_size = src_filename_len + src_ext_len + src_comment_len;
7011

7012
    /* 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) */
7013
    if ((pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_central_dir_following_data_size + 32) >= MZ_UINT32_MAX)
7014
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7015

7016
    num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip);
7017

7018
    if (!pState->m_zip64)
7019
    {
7020
        if (pZip->m_total_files == MZ_UINT16_MAX)
7021
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7022
    }
7023
    else
7024
    {
7025
        /* TODO: Our zip64 support still has some 32-bit limits that may not be worth fixing. */
7026
        if (pZip->m_total_files == MZ_UINT32_MAX)
7027
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7028
    }
7029

7030
    if (!mz_zip_file_stat_internal(pSource_zip, src_file_index, pSrc_central_header, &src_file_stat, NULL))
7031
        return MZ_FALSE;
7032

7033
    cur_src_file_ofs = src_file_stat.m_local_header_ofs;
7034
    cur_dst_file_ofs = pZip->m_archive_size;
7035

7036
    /* Read the source archive's local dir header */
7037
    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)
7038
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7039

7040
    if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG)
7041
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7042

7043
    cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
7044

7045
    /* Compute the total size we need to copy (filename+extra data+compressed data) */
7046
    local_header_filename_size = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS);
7047
    local_header_extra_len = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS);
7048
    local_header_comp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS);
7049
    local_header_uncomp_size = MZ_READ_LE32(pLocal_header + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS);
7050
    src_archive_bytes_remaining = local_header_filename_size + local_header_extra_len + src_file_stat.m_comp_size;
7051

7052
    /* Try to find a zip64 extended information field */
7053
    if ((local_header_extra_len) && ((local_header_comp_size == MZ_UINT32_MAX) || (local_header_uncomp_size == MZ_UINT32_MAX)))
7054
    {
7055
        mz_zip_array file_data_array;
7056
        const mz_uint8 *pExtra_data;
7057
        mz_uint32 extra_size_remaining = local_header_extra_len;
7058

7059
        mz_zip_array_init(&file_data_array, 1);
7060
        if (!mz_zip_array_resize(pZip, &file_data_array, local_header_extra_len, MZ_FALSE))
7061
        {
7062
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7063
        }
7064

7065
        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)
7066
        {
7067
            mz_zip_array_clear(pZip, &file_data_array);
7068
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7069
        }
7070

7071
        pExtra_data = (const mz_uint8 *)file_data_array.m_p;
7072

7073
        do
7074
        {
7075
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7076
            mz_uint32 field_id, field_data_size, field_total_size;
7077

7078
            if (extra_size_remaining < (sizeof(mz_uint16) * 2))
7079
            {
7080
                mz_zip_array_clear(pZip, &file_data_array);
7081
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7082
            }
7083

7084
            field_id = MZ_READ_LE16(pExtra_data);
7085
            field_data_size = MZ_READ_LE16(pExtra_data + sizeof(mz_uint16));
7086
            field_total_size = field_data_size + sizeof(mz_uint16) * 2;
7087

7088
            if (field_total_size > extra_size_remaining)
7089
            {
7090
                mz_zip_array_clear(pZip, &file_data_array);
7091
                return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7092
            }
7093

7094
            if (field_id == MZ_ZIP64_EXTENDED_INFORMATION_FIELD_HEADER_ID)
7095
            {
7096
                const mz_uint8 *pSrc_field_data = pExtra_data + sizeof(mz_uint32);
7097

7098
                if (field_data_size < sizeof(mz_uint64) * 2)
7099
                {
7100
                    mz_zip_array_clear(pZip, &file_data_array);
7101
                    return mz_zip_set_error(pZip, MZ_ZIP_INVALID_HEADER_OR_CORRUPTED);
7102
                }
7103

7104
                // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
7105
                local_header_uncomp_size = MZ_READ_LE64(pSrc_field_data);
7106
                // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
7107
                local_header_comp_size = MZ_READ_LE64(pSrc_field_data + sizeof(mz_uint64)); /* may be 0 if there's a descriptor */
7108

7109
                found_zip64_ext_data_in_ldir = MZ_TRUE;
7110
                break;
7111
            }
7112

7113
            pExtra_data += field_total_size;
7114
            extra_size_remaining -= field_total_size;
7115
        } while (extra_size_remaining);
7116

7117
        mz_zip_array_clear(pZip, &file_data_array);
7118
    }
7119

7120
    if (!pState->m_zip64)
7121
    {
7122
        /* 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). */
7123
        /* We also check when the archive is finalized so this doesn't need to be perfect. */
7124
        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) +
7125
                                            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;
7126

7127
        if (approx_new_archive_size >= MZ_UINT32_MAX)
7128
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7129
    }
7130

7131
    /* Write dest archive padding */
7132
    if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes))
7133
        return MZ_FALSE;
7134

7135
    cur_dst_file_ofs += num_alignment_padding_bytes;
7136

7137
    local_dir_header_ofs = cur_dst_file_ofs;
7138
    if (pZip->m_file_offset_alignment)
7139
    {
7140
        MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0);
7141
    }
7142

7143
    /* 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 */
7144
    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)
7145
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7146

7147
    cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE;
7148

7149
    /* Copy over the source archive bytes to the dest archive, also ensure we have enough buf space to handle optional data descriptor */
7150
    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)))))
7151
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7152

7153
    while (src_archive_bytes_remaining)
7154
    {
7155
        n = (mz_uint)MZ_MIN((mz_uint64)MZ_ZIP_MAX_IO_BUF_SIZE, src_archive_bytes_remaining);
7156
        if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n)
7157
        {
7158
            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7159
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7160
        }
7161
        cur_src_file_ofs += n;
7162

7163
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7164
        {
7165
            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7166
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7167
        }
7168
        cur_dst_file_ofs += n;
7169

7170
        src_archive_bytes_remaining -= n;
7171
    }
7172

7173
    /* Now deal with the optional data descriptor */
7174
    bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS);
7175
    if (bit_flags & 8)
7176
    {
7177
        /* Copy data descriptor */
7178
        if ((pSource_zip->m_pState->m_zip64) || (found_zip64_ext_data_in_ldir))
7179
        {
7180
            /* src is zip64, dest must be zip64 */
7181

7182
            /* name			uint32_t's */
7183
            /* id				1 (optional in zip64?) */
7184
            /* crc			1 */
7185
            /* comp_size	2 */
7186
            /* uncomp_size 2 */
7187
            if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, (sizeof(mz_uint32) * 6)) != (sizeof(mz_uint32) * 6))
7188
            {
7189
                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7190
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7191
            }
7192

7193
            n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID) ? 6 : 5);
7194
        }
7195
        else
7196
        {
7197
            /* src is NOT zip64 */
7198
            // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7199
            mz_bool has_id;
7200

7201
            if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4)
7202
            {
7203
                pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7204
                return mz_zip_set_error(pZip, MZ_ZIP_FILE_READ_FAILED);
7205
            }
7206

7207
            has_id = (MZ_READ_LE32(pBuf) == MZ_ZIP_DATA_DESCRIPTOR_ID);
7208

7209
            if (pZip->m_pState->m_zip64)
7210
            {
7211
                /* dest is zip64, so upgrade the data descriptor */
7212
                const mz_uint32 *pSrc_descriptor = (const mz_uint32 *)((const mz_uint8 *)pBuf + (has_id ? sizeof(mz_uint32) : 0));
7213
                const mz_uint32 src_crc32 = pSrc_descriptor[0];
7214
                const mz_uint64 src_comp_size = pSrc_descriptor[1];
7215
                const mz_uint64 src_uncomp_size = pSrc_descriptor[2];
7216

7217
                mz_write_le32((mz_uint8 *)pBuf, MZ_ZIP_DATA_DESCRIPTOR_ID);
7218
                mz_write_le32((mz_uint8 *)pBuf + sizeof(mz_uint32) * 1, src_crc32);
7219
                mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 2, src_comp_size);
7220
                mz_write_le64((mz_uint8 *)pBuf + sizeof(mz_uint32) * 4, src_uncomp_size);
7221

7222
                n = sizeof(mz_uint32) * 6;
7223
            }
7224
            else
7225
            {
7226
                /* dest is NOT zip64, just copy it as-is */
7227
                n = sizeof(mz_uint32) * (has_id ? 4 : 3);
7228
            }
7229
        }
7230

7231
        if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n)
7232
        {
7233
            pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7234
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7235
        }
7236

7237
        // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores)
7238
        cur_src_file_ofs += n;
7239
        cur_dst_file_ofs += n;
7240
    }
7241
    pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf);
7242

7243
    /* Finally, add the new central dir header */
7244
    orig_central_dir_size = pState->m_central_dir.m_size;
7245

7246
    memcpy(new_central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE);
7247

7248
    if (pState->m_zip64)
7249
    {
7250
        /* 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. */
7251
        const mz_uint8 *pSrc_ext = pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + src_filename_len;
7252
        mz_zip_array new_ext_block;
7253

7254
        mz_zip_array_init(&new_ext_block, sizeof(mz_uint8));
7255

7256
        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7257
        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, MZ_UINT32_MAX);
7258
        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, MZ_UINT32_MAX);
7259

7260
        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))
7261
        {
7262
            mz_zip_array_clear(pZip, &new_ext_block);
7263
            return MZ_FALSE;
7264
        }
7265

7266
        MZ_WRITE_LE16(new_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS, new_ext_block.m_size);
7267

7268
        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7269
        {
7270
            mz_zip_array_clear(pZip, &new_ext_block);
7271
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7272
        }
7273

7274
        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, src_filename_len))
7275
        {
7276
            mz_zip_array_clear(pZip, &new_ext_block);
7277
            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7278
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7279
        }
7280

7281
        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_ext_block.m_p, new_ext_block.m_size))
7282
        {
7283
            mz_zip_array_clear(pZip, &new_ext_block);
7284
            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7285
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7286
        }
7287

7288
        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))
7289
        {
7290
            mz_zip_array_clear(pZip, &new_ext_block);
7291
            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7292
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7293
        }
7294

7295
        mz_zip_array_clear(pZip, &new_ext_block);
7296
    }
7297
    else
7298
    {
7299
        /* sanity checks */
7300
        if (cur_dst_file_ofs > MZ_UINT32_MAX)
7301
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7302

7303
        if (local_dir_header_ofs >= MZ_UINT32_MAX)
7304
            return mz_zip_set_error(pZip, MZ_ZIP_ARCHIVE_TOO_LARGE);
7305

7306
        MZ_WRITE_LE32(new_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs);
7307

7308
        if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, new_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE))
7309
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7310

7311
        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))
7312
        {
7313
            mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7314
            return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7315
        }
7316
    }
7317

7318
    /* This shouldn't trigger unless we screwed up during the initial sanity checks */
7319
    if (pState->m_central_dir.m_size >= MZ_UINT32_MAX)
7320
    {
7321
        /* TODO: Support central dirs >= 32-bits in size */
7322
        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7323
        return mz_zip_set_error(pZip, MZ_ZIP_UNSUPPORTED_CDIR_SIZE);
7324
    }
7325

7326
    n = (mz_uint32)orig_central_dir_size;
7327
    if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1))
7328
    {
7329
        mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE);
7330
        return mz_zip_set_error(pZip, MZ_ZIP_ALLOC_FAILED);
7331
    }
7332

7333
    pZip->m_total_files++;
7334
    pZip->m_archive_size = cur_dst_file_ofs;
7335

7336
    return MZ_TRUE;
7337
}
7338

7339
mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip)
7340
{
7341
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7342
    mz_zip_internal_state *pState;
7343
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7344
    mz_uint64 central_dir_ofs, central_dir_size;
7345
    mz_uint8 hdr[256];
7346

7347
    if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING))
7348
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7349

7350
    pState = pZip->m_pState;
7351

7352
    if (pState->m_zip64)
7353
    {
7354
        if ((pZip->m_total_files > MZ_UINT32_MAX) || (pState->m_central_dir.m_size >= MZ_UINT32_MAX))
7355
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7356
    }
7357
    else
7358
    {
7359
        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))
7360
            return mz_zip_set_error(pZip, MZ_ZIP_TOO_MANY_FILES);
7361
    }
7362

7363
    central_dir_ofs = 0;
7364
    central_dir_size = 0;
7365
    if (pZip->m_total_files)
7366
    {
7367
        /* Write central directory */
7368
        central_dir_ofs = pZip->m_archive_size;
7369
        central_dir_size = pState->m_central_dir.m_size;
7370
        pZip->m_central_directory_file_ofs = central_dir_ofs;
7371
        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)
7372
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7373

7374
        pZip->m_archive_size += central_dir_size;
7375
    }
7376

7377
    if (pState->m_zip64)
7378
    {
7379
        /* Write zip64 end of central directory header */
7380
        mz_uint64 rel_ofs_to_zip64_ecdr = pZip->m_archive_size;
7381

7382
        MZ_CLEAR_OBJ(hdr);
7383
        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDH_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIG);
7384
        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));
7385
        MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_MADE_BY_OFS, 0x031E); /* TODO: always Unix */
7386
        MZ_WRITE_LE16(hdr + MZ_ZIP64_ECDH_VERSION_NEEDED_OFS, 0x002D);
7387
        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files);
7388
        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files);
7389
        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_SIZE_OFS, central_dir_size);
7390
        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDH_CDIR_OFS_OFS, central_dir_ofs);
7391
        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)
7392
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7393

7394
        pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_HEADER_SIZE;
7395

7396
        /* Write zip64 end of central directory locator */
7397
        MZ_CLEAR_OBJ(hdr);
7398
        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_SIG_OFS, MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIG);
7399
        MZ_WRITE_LE64(hdr + MZ_ZIP64_ECDL_REL_OFS_TO_ZIP64_ECDR_OFS, rel_ofs_to_zip64_ecdr);
7400
        MZ_WRITE_LE32(hdr + MZ_ZIP64_ECDL_TOTAL_NUMBER_OF_DISKS_OFS, 1);
7401
        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)
7402
            return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7403

7404
        pZip->m_archive_size += MZ_ZIP64_END_OF_CENTRAL_DIR_LOCATOR_SIZE;
7405
    }
7406

7407
    /* Write end of central directory record */
7408
    MZ_CLEAR_OBJ(hdr);
7409
    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG);
7410
    MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7411
    MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, MZ_MIN(MZ_UINT16_MAX, pZip->m_total_files));
7412
    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_size));
7413
    MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, MZ_MIN(MZ_UINT32_MAX, central_dir_ofs));
7414

7415
    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)
7416
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_WRITE_FAILED);
7417

7418
#ifndef MINIZ_NO_STDIO
7419
    if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF))
7420
        return mz_zip_set_error(pZip, MZ_ZIP_FILE_CLOSE_FAILED);
7421
#endif /* #ifndef MINIZ_NO_STDIO */
7422

7423
    pZip->m_archive_size += MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE;
7424

7425
    pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED;
7426
    return MZ_TRUE;
7427
}
7428

7429
mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize)
7430
{
7431
    if ((!ppBuf) || (!pSize))
7432
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7433

7434
    *ppBuf = NULL;
7435
    *pSize = 0;
7436

7437
    if ((!pZip) || (!pZip->m_pState))
7438
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7439

7440
    if (pZip->m_pWrite != mz_zip_heap_write_func)
7441
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7442

7443
    if (!mz_zip_writer_finalize_archive(pZip))
7444
        return MZ_FALSE;
7445

7446
    *ppBuf = pZip->m_pState->m_pMem;
7447
    *pSize = pZip->m_pState->m_mem_size;
7448
    pZip->m_pState->m_pMem = NULL;
7449
    pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0;
7450

7451
    return MZ_TRUE;
7452
}
7453

7454
mz_bool mz_zip_writer_end(mz_zip_archive *pZip)
7455
{
7456
    return mz_zip_writer_end_internal(pZip, MZ_TRUE);
7457
}
7458

7459
#ifndef MINIZ_NO_STDIO
7460
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)
7461
{
7462
    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);
7463
}
7464

7465
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)
7466
{
7467
    mz_bool status, created_new_archive = MZ_FALSE;
7468
    mz_zip_archive zip_archive;
7469
    struct MZ_FILE_STAT_STRUCT file_stat;
7470
    mz_zip_error actual_err = MZ_ZIP_NO_ERROR;
7471

7472
    mz_zip_zero_struct(&zip_archive);
7473
    if ((int)level_and_flags < 0)
7474
        level_and_flags = MZ_DEFAULT_LEVEL;
7475

7476
    if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION))
7477
    {
7478
        if (pErr)
7479
            *pErr = MZ_ZIP_INVALID_PARAMETER;
7480
        return MZ_FALSE;
7481
    }
7482

7483
    if (!mz_zip_writer_validate_archive_name(pArchive_name))
7484
    {
7485
        if (pErr)
7486
            *pErr = MZ_ZIP_INVALID_FILENAME;
7487
        return MZ_FALSE;
7488
    }
7489

7490
    /* 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. */
7491
    /* So be sure to compile with _LARGEFILE64_SOURCE 1 */
7492
    if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0)
7493
    {
7494
        /* Create a new archive. */
7495
        if (!mz_zip_writer_init_file_v2(&zip_archive, pZip_filename, 0, level_and_flags))
7496
        {
7497
            if (pErr)
7498
                *pErr = zip_archive.m_last_error;
7499
            return MZ_FALSE;
7500
        }
7501

7502
        created_new_archive = MZ_TRUE;
7503
    }
7504
    else
7505
    {
7506
        /* Append to an existing archive. */
7507
        if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7508
        {
7509
            if (pErr)
7510
                *pErr = zip_archive.m_last_error;
7511
            return MZ_FALSE;
7512
        }
7513

7514
        if (!mz_zip_writer_init_from_reader_v2(&zip_archive, pZip_filename, level_and_flags))
7515
        {
7516
            if (pErr)
7517
                *pErr = zip_archive.m_last_error;
7518

7519
            mz_zip_reader_end_internal(&zip_archive, MZ_FALSE);
7520

7521
            return MZ_FALSE;
7522
        }
7523
    }
7524

7525
    status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0);
7526
    actual_err = zip_archive.m_last_error;
7527

7528
    /* 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.) */
7529
    if (!mz_zip_writer_finalize_archive(&zip_archive))
7530
    {
7531
        if (!actual_err)
7532
            actual_err = zip_archive.m_last_error;
7533

7534
        status = MZ_FALSE;
7535
    }
7536

7537
    if (!mz_zip_writer_end_internal(&zip_archive, status))
7538
    {
7539
        if (!actual_err)
7540
            actual_err = zip_archive.m_last_error;
7541

7542
        status = MZ_FALSE;
7543
    }
7544

7545
    if ((!status) && (created_new_archive))
7546
    {
7547
        /* It's a new archive and something went wrong, so just delete it. */
7548
        int ignoredStatus = MZ_DELETE_FILE(pZip_filename);
7549
        (void)ignoredStatus;
7550
    }
7551

7552
    if (pErr)
7553
        *pErr = actual_err;
7554

7555
    return status;
7556
}
7557

7558
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)
7559
{
7560
    mz_uint32 file_index;
7561
    mz_zip_archive zip_archive;
7562
    void *p = NULL;
7563

7564
    if (pSize)
7565
        *pSize = 0;
7566

7567
    if ((!pZip_filename) || (!pArchive_name))
7568
    {
7569
        if (pErr)
7570
            *pErr = MZ_ZIP_INVALID_PARAMETER;
7571

7572
        return NULL;
7573
    }
7574

7575
    mz_zip_zero_struct(&zip_archive);
7576
    if (!mz_zip_reader_init_file_v2(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY, 0, 0))
7577
    {
7578
        if (pErr)
7579
            *pErr = zip_archive.m_last_error;
7580

7581
        return NULL;
7582
    }
7583

7584
    if (mz_zip_reader_locate_file_v2(&zip_archive, pArchive_name, pComment, flags, &file_index))
7585
    {
7586
        p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags);
7587
    }
7588

7589
    mz_zip_reader_end_internal(&zip_archive, p != NULL);
7590

7591
    if (pErr)
7592
        *pErr = zip_archive.m_last_error;
7593

7594
    return p;
7595
}
7596

7597
void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags)
7598
{
7599
    return mz_zip_extract_archive_file_to_heap_v2(pZip_filename, pArchive_name, NULL, pSize, flags, NULL);
7600
}
7601

7602
#endif /* #ifndef MINIZ_NO_STDIO */
7603

7604
#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
7605

7606
/* ------------------- Misc utils */
7607

7608
mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip)
7609
{
7610
    return pZip ? pZip->m_zip_mode : MZ_ZIP_MODE_INVALID;
7611
}
7612

7613
mz_zip_type mz_zip_get_type(mz_zip_archive *pZip)
7614
{
7615
    return pZip ? pZip->m_zip_type : MZ_ZIP_TYPE_INVALID;
7616
}
7617

7618
mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num)
7619
{
7620
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7621
    mz_zip_error prev_err;
7622

7623
    if (!pZip)
7624
        return MZ_ZIP_INVALID_PARAMETER;
7625

7626
    prev_err = pZip->m_last_error;
7627

7628
    pZip->m_last_error = err_num;
7629
    return prev_err;
7630
}
7631

7632
mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip)
7633
{
7634
    if (!pZip)
7635
        return MZ_ZIP_INVALID_PARAMETER;
7636

7637
    return pZip->m_last_error;
7638
}
7639

7640
mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip)
7641
{
7642
    return mz_zip_set_last_error(pZip, MZ_ZIP_NO_ERROR);
7643
}
7644

7645
mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip)
7646
{
7647
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7648
    mz_zip_error prev_err;
7649

7650
    if (!pZip)
7651
        return MZ_ZIP_INVALID_PARAMETER;
7652

7653
    prev_err = pZip->m_last_error;
7654

7655
    pZip->m_last_error = MZ_ZIP_NO_ERROR;
7656
    return prev_err;
7657
}
7658

7659
const char *mz_zip_get_error_string(mz_zip_error mz_err)
7660
{
7661
    switch (mz_err)
7662
    {
7663
        case MZ_ZIP_NO_ERROR:
7664
            return "no error";
7665
        case MZ_ZIP_UNDEFINED_ERROR:
7666
            return "undefined error";
7667
        case MZ_ZIP_TOO_MANY_FILES:
7668
            return "too many files";
7669
        case MZ_ZIP_FILE_TOO_LARGE:
7670
            return "file too large";
7671
        case MZ_ZIP_UNSUPPORTED_METHOD:
7672
            return "unsupported method";
7673
        case MZ_ZIP_UNSUPPORTED_ENCRYPTION:
7674
            return "unsupported encryption";
7675
        case MZ_ZIP_UNSUPPORTED_FEATURE:
7676
            return "unsupported feature";
7677
        case MZ_ZIP_FAILED_FINDING_CENTRAL_DIR:
7678
            return "failed finding central directory";
7679
        case MZ_ZIP_NOT_AN_ARCHIVE:
7680
            return "not a ZIP archive";
7681
        case MZ_ZIP_INVALID_HEADER_OR_CORRUPTED:
7682
            return "invalid header or archive is corrupted";
7683
        case MZ_ZIP_UNSUPPORTED_MULTIDISK:
7684
            return "unsupported multidisk archive";
7685
        case MZ_ZIP_DECOMPRESSION_FAILED:
7686
            return "decompression failed or archive is corrupted";
7687
        case MZ_ZIP_COMPRESSION_FAILED:
7688
            return "compression failed";
7689
        case MZ_ZIP_UNEXPECTED_DECOMPRESSED_SIZE:
7690
            return "unexpected decompressed size";
7691
        case MZ_ZIP_CRC_CHECK_FAILED:
7692
            return "CRC-32 check failed";
7693
        case MZ_ZIP_UNSUPPORTED_CDIR_SIZE:
7694
            return "unsupported central directory size";
7695
        case MZ_ZIP_ALLOC_FAILED:
7696
            return "allocation failed";
7697
        case MZ_ZIP_FILE_OPEN_FAILED:
7698
            return "file open failed";
7699
        case MZ_ZIP_FILE_CREATE_FAILED:
7700
            return "file create failed";
7701
        case MZ_ZIP_FILE_WRITE_FAILED:
7702
            return "file write failed";
7703
        case MZ_ZIP_FILE_READ_FAILED:
7704
            return "file read failed";
7705
        case MZ_ZIP_FILE_CLOSE_FAILED:
7706
            return "file close failed";
7707
        case MZ_ZIP_FILE_SEEK_FAILED:
7708
            return "file seek failed";
7709
        case MZ_ZIP_FILE_STAT_FAILED:
7710
            return "file stat failed";
7711
        case MZ_ZIP_INVALID_PARAMETER:
7712
            return "invalid parameter";
7713
        case MZ_ZIP_INVALID_FILENAME:
7714
            return "invalid filename";
7715
        case MZ_ZIP_BUF_TOO_SMALL:
7716
            return "buffer too small";
7717
        case MZ_ZIP_INTERNAL_ERROR:
7718
            return "internal error";
7719
        case MZ_ZIP_FILE_NOT_FOUND:
7720
            return "file not found";
7721
        case MZ_ZIP_ARCHIVE_TOO_LARGE:
7722
            return "archive is too large";
7723
        case MZ_ZIP_VALIDATION_FAILED:
7724
            return "validation failed";
7725
        case MZ_ZIP_WRITE_CALLBACK_FAILED:
7726
            return "write calledback failed";
7727
        default:
7728
            break;
7729
    }
7730

7731
    return "unknown error";
7732
}
7733

7734
/* Note: Just because the archive is not zip64 doesn't necessarily mean it doesn't have Zip64 extended information extra field, argh. */
7735
mz_bool mz_zip_is_zip64(mz_zip_archive *pZip)
7736
{
7737
    if ((!pZip) || (!pZip->m_pState))
7738
        return MZ_FALSE;
7739

7740
    return pZip->m_pState->m_zip64;
7741
}
7742

7743
size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip)
7744
{
7745
    if ((!pZip) || (!pZip->m_pState))
7746
        return 0;
7747

7748
    return pZip->m_pState->m_central_dir.m_size;
7749
}
7750

7751
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip)
7752
{
7753
    return pZip ? pZip->m_total_files : 0;
7754
}
7755

7756
mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip)
7757
{
7758
    if (!pZip)
7759
        return 0;
7760
    return pZip->m_archive_size;
7761
}
7762

7763
mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip)
7764
{
7765
    if ((!pZip) || (!pZip->m_pState))
7766
        return 0;
7767
    return pZip->m_pState->m_file_archive_start_ofs;
7768
}
7769

7770
MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip)
7771
{
7772
    if ((!pZip) || (!pZip->m_pState))
7773
        return 0;
7774
    return pZip->m_pState->m_pFile;
7775
}
7776

7777
size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n)
7778
{
7779
    if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pZip->m_pRead))
7780
        return mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7781

7782
    return pZip->m_pRead(pZip->m_pIO_opaque, file_ofs, pBuf, n);
7783
}
7784

7785
mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size)
7786
{
7787
    // NOLINTNEXTLINE(cppcoreguidelines-init-variables)
7788
    mz_uint n;
7789
    const mz_uint8 *p = mz_zip_get_cdh(pZip, file_index);
7790
    if (!p)
7791
    {
7792
        if (filename_buf_size)
7793
            pFilename[0] = '\0';
7794
        mz_zip_set_error(pZip, MZ_ZIP_INVALID_PARAMETER);
7795
        return 0;
7796
    }
7797
    n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS);
7798
    if (filename_buf_size)
7799
    {
7800
        n = MZ_MIN(n, filename_buf_size - 1);
7801
        memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n);
7802
        pFilename[n] = '\0';
7803
    }
7804
    return n + 1;
7805
}
7806

7807
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat)
7808
{
7809
    return mz_zip_file_stat_internal(pZip, file_index, mz_zip_get_cdh(pZip, file_index), pStat, NULL);
7810
}
7811

7812
mz_bool mz_zip_end(mz_zip_archive *pZip)
7813
{
7814
    if (!pZip)
7815
        return MZ_FALSE;
7816

7817
    if (pZip->m_zip_mode == MZ_ZIP_MODE_READING)
7818
        return mz_zip_reader_end(pZip);
7819
#ifndef MINIZ_NO_ARCHIVE_WRITING_APIS
7820
    else if ((pZip->m_zip_mode == MZ_ZIP_MODE_WRITING) || (pZip->m_zip_mode == MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))
7821
        return mz_zip_writer_end(pZip);
7822
#endif
7823

7824
    return MZ_FALSE;
7825
}
7826

7827
#ifdef __cplusplus
7828
}
7829
#endif
7830

7831
#endif /*#ifndef MINIZ_NO_ARCHIVE_APIS*/
7832

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.