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