LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_zip.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 245 321 76.3 %
Date: 2026-04-07 13:24:38 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 1995-1997 Sam Leffler
       3             :  * Copyright (c) 1995-1997 Silicon Graphics, Inc.
       4             :  *
       5             :  * Permission to use, copy, modify, distribute, and sell this software and
       6             :  * its documentation for any purpose is hereby granted without fee, provided
       7             :  * that (i) the above copyright notices and this permission notice appear in
       8             :  * all copies of the software and related documentation, and (ii) the names of
       9             :  * Sam Leffler and Silicon Graphics may not be used in any advertising or
      10             :  * publicity relating to the software without the specific, prior written
      11             :  * permission of Sam Leffler and Silicon Graphics.
      12             :  *
      13             :  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
      14             :  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
      15             :  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
      16             :  *
      17             :  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
      18             :  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
      19             :  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
      20             :  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
      21             :  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
      22             :  * OF THIS SOFTWARE.
      23             :  */
      24             : 
      25             : #include "tiffiop.h"
      26             : #ifdef ZIP_SUPPORT
      27             : /*
      28             :  * TIFF Library.
      29             :  *
      30             :  * ZIP (aka Deflate) Compression Support
      31             :  *
      32             :  * This file is an interface to the zlib library written by
      33             :  * Jean-loup Gailly and Mark Adler.  You must use version 1.0 or later
      34             :  * of the library.
      35             :  *
      36             :  * Optionally, libdeflate (https://github.com/ebiggers/libdeflate) may be used
      37             :  * to do the compression and decompression, but only for whole strips and tiles.
      38             :  * For scanline access, zlib will be sued as a fallback.
      39             :  */
      40             : #include "tif_predict.h"
      41             : #include "zlib.h"
      42             : 
      43             : #if LIBDEFLATE_SUPPORT
      44             : #include "libdeflate.h"
      45             : #endif
      46             : #define LIBDEFLATE_MAX_COMPRESSION_LEVEL 12
      47             : 
      48             : #include <stdio.h>
      49             : 
      50             : /*
      51             :  * Sigh, ZLIB_VERSION is defined as a string so there's no
      52             :  * way to do a proper check here.  Instead we guess based
      53             :  * on the presence of #defines that were added between the
      54             :  * 0.95 and 1.0 distributions.
      55             :  */
      56             : #if !defined(Z_NO_COMPRESSION) || !defined(Z_DEFLATED)
      57             : #error "Antiquated ZLIB software; you must use version 1.0 or later"
      58             : #endif
      59             : 
      60             : #define SAFE_MSG(sp) ((sp)->stream.msg == NULL ? "" : (sp)->stream.msg)
      61             : 
      62             : /*
      63             :  * State block for each open TIFF
      64             :  * file using ZIP compression/decompression.
      65             :  */
      66             : typedef struct
      67             : {
      68             :     TIFFPredictorState predict;
      69             :     z_stream stream;
      70             :     int read_error; /* whether a read error has occurred, and which should cause
      71             :                        further reads in the same strip/tile to be aborted */
      72             :     int zipquality; /* compression level */
      73             :     int state;      /* state flags */
      74             :     int subcodec;   /* DEFLATE_SUBCODEC_ZLIB or DEFLATE_SUBCODEC_LIBDEFLATE */
      75             : #if LIBDEFLATE_SUPPORT
      76             :     int libdeflate_state; /* -1 = until first time ZIPEncode() / ZIPDecode() is
      77             :                              called, 0 = use zlib, 1 = use libdeflate */
      78             :     struct libdeflate_decompressor *libdeflate_dec;
      79             :     struct libdeflate_compressor *libdeflate_enc;
      80             : #endif
      81             : #define ZSTATE_INIT_DECODE 0x01
      82             : #define ZSTATE_INIT_ENCODE 0x02
      83             : 
      84             :     TIFFVGetMethod vgetparent; /* super-class method */
      85             :     TIFFVSetMethod vsetparent; /* super-class method */
      86             : } ZIPState;
      87             : 
      88             : #define GetZIPState(tif) ((ZIPState *)(tif)->tif_data)
      89             : #define ZIPDecoderState(tif) GetZIPState(tif)
      90             : #define ZIPEncoderState(tif) GetZIPState(tif)
      91             : 
      92             : static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
      93             : static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
      94             : 
      95        2405 : static int ZIPFixupTags(TIFF *tif)
      96             : {
      97             :     (void)tif;
      98        2405 :     return (1);
      99             : }
     100             : 
     101         568 : static int ZIPSetupDecode(TIFF *tif)
     102             : {
     103             :     static const char module[] = "ZIPSetupDecode";
     104         568 :     ZIPState *sp = ZIPDecoderState(tif);
     105             : 
     106         568 :     assert(sp != NULL);
     107             : 
     108             :     /* if we were last encoding, terminate this mode */
     109         568 :     if (sp->state & ZSTATE_INIT_ENCODE)
     110             :     {
     111          15 :         deflateEnd(&sp->stream);
     112          15 :         sp->state = 0;
     113             :     }
     114             : 
     115             :     /* This function can possibly be called several times by */
     116             :     /* PredictorSetupDecode() if this function succeeds but */
     117             :     /* PredictorSetup() fails */
     118        1136 :     if ((sp->state & ZSTATE_INIT_DECODE) == 0 &&
     119         568 :         inflateInit(&sp->stream) != Z_OK)
     120             :     {
     121           0 :         TIFFErrorExtR(tif, module, "%s", SAFE_MSG(sp));
     122           0 :         return (0);
     123             :     }
     124             :     else
     125             :     {
     126         568 :         sp->state |= ZSTATE_INIT_DECODE;
     127         568 :         return (1);
     128             :     }
     129             : }
     130             : 
     131       19232 : static inline uint64_t TIFF_MIN_UINT64(uint64_t a, uint64_t b)
     132             : {
     133       19232 :     return a < b ? a : b;
     134             : }
     135             : 
     136       19232 : static inline uInt TIFF_CLAMP_UINT64_TO_INT32_MAX(uint64_t v)
     137             : {
     138       19232 :     return (uInt)TIFF_MIN_UINT64(v, INT32_MAX);
     139             : }
     140             : 
     141             : /*
     142             :  * Setup state for decoding a strip.
     143             :  */
     144        8784 : static int ZIPPreDecode(TIFF *tif, uint16_t s)
     145             : {
     146        8784 :     ZIPState *sp = ZIPDecoderState(tif);
     147             : 
     148             :     (void)s;
     149        8784 :     assert(sp != NULL);
     150             : 
     151        8784 :     if ((sp->state & ZSTATE_INIT_DECODE) == 0)
     152          15 :         tif->tif_setupdecode(tif);
     153             : 
     154             : #if LIBDEFLATE_SUPPORT
     155        8784 :     sp->libdeflate_state = -1;
     156             : #endif
     157        8784 :     sp->stream.next_in = tif->tif_rawdata;
     158             :     assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
     159             :          we need to simplify this code to reflect a ZLib that is likely updated
     160             :          to deal with 8byte memory sizes, though this code will respond
     161             :          appropriately even before we simplify it */
     162        8784 :     sp->stream.avail_in =
     163        8784 :         TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)tif->tif_rawcc);
     164        8784 :     if (inflateReset(&sp->stream) == Z_OK)
     165             :     {
     166        8784 :         sp->read_error = 0;
     167        8784 :         return 1;
     168             :     }
     169           0 :     return 0;
     170             : }
     171             : 
     172       10784 : static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
     173             : {
     174             :     static const char module[] = "ZIPDecode";
     175       10784 :     ZIPState *sp = ZIPDecoderState(tif);
     176             : 
     177             :     (void)s;
     178       10784 :     assert(sp != NULL);
     179       10784 :     assert(sp->state == ZSTATE_INIT_DECODE);
     180             : 
     181       10784 :     if (sp->read_error)
     182             :     {
     183           0 :         memset(op, 0, (size_t)occ);
     184           0 :         TIFFErrorExtR(tif, module,
     185             :                       "ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
     186             :                       "previous error",
     187             :                       tif->tif_row);
     188           0 :         return 0;
     189             :     }
     190             : 
     191             : #if LIBDEFLATE_SUPPORT
     192       10784 :     if (sp->libdeflate_state == 1)
     193           0 :         return 0;
     194             : 
     195             :     /* If we have libdeflate support and we are asked to read a whole */
     196             :     /* strip/tile, then go for using it */
     197             :     do
     198             :     {
     199       10784 :         TIFFDirectory *td = &tif->tif_dir;
     200             : 
     201       10784 :         if (sp->libdeflate_state == 0)
     202        2000 :             break;
     203        8784 :         if (sp->subcodec == DEFLATE_SUBCODEC_ZLIB)
     204           0 :             break;
     205             : 
     206             :         /* Check if we are in the situation where we can use libdeflate */
     207        8784 :         if (isTiled(tif))
     208             :         {
     209        1047 :             if (TIFFTileSize64(tif) != (uint64_t)occ)
     210         173 :                 break;
     211             :         }
     212             :         else
     213             :         {
     214        7737 :             uint32_t strip_height = td->td_imagelength - tif->tif_row;
     215        7737 :             if (strip_height > td->td_rowsperstrip)
     216        6906 :                 strip_height = td->td_rowsperstrip;
     217        7737 :             if (TIFFVStripSize64(tif, strip_height) != (uint64_t)occ)
     218           2 :                 break;
     219             :         }
     220             : 
     221             :         /* Check for overflow */
     222             :         if ((size_t)tif->tif_rawcc != (uint64_t)tif->tif_rawcc)
     223             :             break;
     224             :         if ((size_t)occ != (uint64_t)occ)
     225             :             break;
     226             : 
     227             :         /* Go for decompression using libdeflate */
     228             :         {
     229             :             enum libdeflate_result res;
     230        8609 :             if (sp->libdeflate_dec == NULL)
     231             :             {
     232         505 :                 sp->libdeflate_dec = libdeflate_alloc_decompressor();
     233         505 :                 if (sp->libdeflate_dec == NULL)
     234             :                 {
     235           0 :                     break;
     236             :                 }
     237             :             }
     238             : 
     239        8609 :             sp->libdeflate_state = 1;
     240             : 
     241        8609 :             res = libdeflate_zlib_decompress(sp->libdeflate_dec, tif->tif_rawcp,
     242        8609 :                                              (size_t)tif->tif_rawcc, op,
     243             :                                              (size_t)occ, NULL);
     244             : 
     245        8609 :             tif->tif_rawcp += tif->tif_rawcc;
     246        8609 :             tif->tif_rawcc = 0;
     247             : 
     248             :             /* We accept LIBDEFLATE_INSUFFICIENT_SPACE has a return */
     249             :             /* There are odd files in the wild where the last strip, when */
     250             :             /* it is smaller in height than td_rowsperstrip, actually contains
     251             :              */
     252             :             /* data for td_rowsperstrip lines. Just ignore that silently. */
     253        8609 :             if (res != LIBDEFLATE_SUCCESS &&
     254             :                 res != LIBDEFLATE_INSUFFICIENT_SPACE)
     255             :             {
     256           0 :                 memset(op, 0, (size_t)occ);
     257           0 :                 TIFFErrorExtR(tif, module, "Decoding error at scanline %lu",
     258           0 :                               (unsigned long)tif->tif_row);
     259           0 :                 sp->read_error = 1;
     260           0 :                 return 0;
     261             :             }
     262             : 
     263        8609 :             return 1;
     264             :         }
     265             :     } while (0);
     266        2175 :     sp->libdeflate_state = 0;
     267             : #endif /* LIBDEFLATE_SUPPORT */
     268             : 
     269        2175 :     sp->stream.next_in = tif->tif_rawcp;
     270             : 
     271        2175 :     sp->stream.next_out = op;
     272             :     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
     273             :          we need to simplify this code to reflect a ZLib that is likely updated
     274             :          to deal with 8byte memory sizes, though this code will respond
     275             :          appropriately even before we simplify it */
     276             :     do
     277             :     {
     278             :         int state;
     279             :         uInt avail_in_before =
     280        2175 :             TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)tif->tif_rawcc);
     281        2175 :         uInt avail_out_before = TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)occ);
     282        2175 :         sp->stream.avail_in = avail_in_before;
     283        2175 :         sp->stream.avail_out = avail_out_before;
     284        2175 :         state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
     285        2175 :         tif->tif_rawcc -= (avail_in_before - sp->stream.avail_in);
     286        2175 :         occ -= (avail_out_before - sp->stream.avail_out);
     287        2175 :         if (state == Z_STREAM_END)
     288           1 :             break;
     289        2174 :         if (state == Z_DATA_ERROR)
     290             :         {
     291           1 :             memset(sp->stream.next_out, 0, (size_t)occ);
     292           1 :             TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s",
     293           2 :                           (unsigned long)tif->tif_row, SAFE_MSG(sp));
     294           1 :             sp->read_error = 1;
     295           1 :             return (0);
     296             :         }
     297        2173 :         if (state != Z_OK)
     298             :         {
     299           0 :             memset(sp->stream.next_out, 0, (size_t)occ);
     300           0 :             TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
     301           0 :             sp->read_error = 1;
     302           0 :             return (0);
     303             :         }
     304        2173 :     } while (occ > 0);
     305        2174 :     if (occ != 0)
     306             :     {
     307           0 :         TIFFErrorExtR(tif, module,
     308             :                       "Not enough data at scanline %lu (short %" PRIu64
     309             :                       " bytes)",
     310           0 :                       (unsigned long)tif->tif_row, (uint64_t)occ);
     311           0 :         memset(sp->stream.next_out, 0, (size_t)occ);
     312           0 :         sp->read_error = 1;
     313           0 :         return (0);
     314             :     }
     315             : 
     316        2174 :     tif->tif_rawcp = sp->stream.next_in;
     317             : 
     318        2174 :     return (1);
     319             : }
     320             : 
     321        5744 : static int ZIPSetupEncode(TIFF *tif)
     322             : {
     323             :     static const char module[] = "ZIPSetupEncode";
     324        5744 :     ZIPState *sp = ZIPEncoderState(tif);
     325             :     int cappedQuality;
     326             : 
     327        5744 :     assert(sp != NULL);
     328        5744 :     if (sp->state & ZSTATE_INIT_DECODE)
     329             :     {
     330           8 :         inflateEnd(&sp->stream);
     331           8 :         sp->state = 0;
     332             :     }
     333             : 
     334        5744 :     cappedQuality = sp->zipquality;
     335        5744 :     if (cappedQuality > Z_BEST_COMPRESSION)
     336           0 :         cappedQuality = Z_BEST_COMPRESSION;
     337             : 
     338        5744 :     if (deflateInit(&sp->stream, cappedQuality) != Z_OK)
     339             :     {
     340           0 :         TIFFErrorExtR(tif, module, "%s", SAFE_MSG(sp));
     341           0 :         return (0);
     342             :     }
     343             :     else
     344             :     {
     345        5745 :         sp->state |= ZSTATE_INIT_ENCODE;
     346        5745 :         return (1);
     347             :     }
     348             : }
     349             : 
     350             : /*
     351             :  * Reset encoding state at the start of a strip.
     352             :  */
     353       16541 : static int ZIPPreEncode(TIFF *tif, uint16_t s)
     354             : {
     355       16541 :     ZIPState *sp = ZIPEncoderState(tif);
     356             : 
     357             :     (void)s;
     358       16541 :     assert(sp != NULL);
     359       16541 :     if (sp->state != ZSTATE_INIT_ENCODE)
     360           8 :         tif->tif_setupencode(tif);
     361             : 
     362             : #if LIBDEFLATE_SUPPORT
     363       16527 :     sp->libdeflate_state = -1;
     364             : #endif
     365       16527 :     sp->stream.next_out = tif->tif_rawdata;
     366             :     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
     367             :          we need to simplify this code to reflect a ZLib that is likely updated
     368             :          to deal with 8byte memory sizes, though this code will respond
     369             :          appropriately even before we simplify it */
     370       33054 :     sp->stream.avail_out = (uint64_t)tif->tif_rawdatasize <= 0xFFFFFFFFU
     371       16529 :                                ? (uInt)tif->tif_rawdatasize
     372       16527 :                                : 0xFFFFFFFFU;
     373       16527 :     return (deflateReset(&sp->stream) == Z_OK);
     374             : }
     375             : 
     376             : /*
     377             :  * Encode a chunk of pixels.
     378             :  */
     379       18532 : static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
     380             : {
     381             :     static const char module[] = "ZIPEncode";
     382       18532 :     ZIPState *sp = ZIPEncoderState(tif);
     383             : 
     384       18532 :     assert(sp != NULL);
     385       18532 :     assert(sp->state == ZSTATE_INIT_ENCODE);
     386             : 
     387             :     (void)s;
     388             : 
     389             : #if LIBDEFLATE_SUPPORT
     390       18532 :     if (sp->libdeflate_state == 1)
     391           0 :         return 0;
     392             : 
     393             :     /* If we have libdeflate support and we are asked to write a whole */
     394             :     /* strip/tile, then go for using it */
     395             :     do
     396             :     {
     397       18532 :         TIFFDirectory *td = &tif->tif_dir;
     398             : 
     399       18532 :         if (sp->libdeflate_state == 0)
     400        2000 :             break;
     401       16532 :         if (sp->subcodec == DEFLATE_SUBCODEC_ZLIB)
     402        4097 :             break;
     403             : 
     404             :         /* Libdeflate does not support the 0-compression level */
     405       12435 :         if (sp->zipquality == Z_NO_COMPRESSION)
     406           0 :             break;
     407             : 
     408             :         /* Check if we are in the situation where we can use libdeflate */
     409       12435 :         if (isTiled(tif))
     410             :         {
     411        5727 :             if (TIFFTileSize64(tif) != (uint64_t)cc)
     412           0 :                 break;
     413             :         }
     414             :         else
     415             :         {
     416        6708 :             uint32_t strip_height = td->td_imagelength - tif->tif_row;
     417        6708 :             if (strip_height > td->td_rowsperstrip)
     418        5248 :                 strip_height = td->td_rowsperstrip;
     419        6708 :             if (TIFFVStripSize64(tif, strip_height) != (uint64_t)cc)
     420           1 :                 break;
     421             :         }
     422             : 
     423             :         /* Check for overflow */
     424             :         if ((size_t)tif->tif_rawdatasize != (uint64_t)tif->tif_rawdatasize)
     425             :             break;
     426             :         if ((size_t)cc != (uint64_t)cc)
     427             :             break;
     428             : 
     429             :         /* Go for compression using libdeflate */
     430             :         {
     431             :             size_t nCompressedBytes;
     432       12443 :             if (sp->libdeflate_enc == NULL)
     433             :             {
     434             :                 /* To get results as good as zlib, we asked for an extra */
     435             :                 /* level of compression */
     436        1642 :                 sp->libdeflate_enc = libdeflate_alloc_compressor(
     437        1642 :                     sp->zipquality == Z_DEFAULT_COMPRESSION ? 7
     438          12 :                     : sp->zipquality >= 6 && sp->zipquality <= 9
     439          12 :                         ? sp->zipquality + 1
     440          32 :                         : sp->zipquality);
     441        1641 :                 if (sp->libdeflate_enc == NULL)
     442             :                 {
     443           0 :                     TIFFErrorExtR(tif, module, "Cannot allocate compressor");
     444           0 :                     break;
     445             :                 }
     446             :             }
     447             : 
     448             :             /* Make sure the output buffer is large enough for the worse case.
     449             :              */
     450             :             /* In TIFFWriteBufferSetup(), when libtiff allocates the buffer */
     451             :             /* we've taken a 10% margin over the uncompressed size, which should
     452             :              */
     453             :             /* be large enough even for the the worse case scenario. */
     454       12442 :             if (libdeflate_zlib_compress_bound(sp->libdeflate_enc, (size_t)cc) >
     455       12440 :                 (size_t)tif->tif_rawdatasize)
     456             :             {
     457           0 :                 break;
     458             :             }
     459             : 
     460       12440 :             sp->libdeflate_state = 1;
     461       12440 :             nCompressedBytes = libdeflate_zlib_compress(
     462       12440 :                 sp->libdeflate_enc, bp, (size_t)cc, tif->tif_rawdata,
     463       12440 :                 (size_t)tif->tif_rawdatasize);
     464             : 
     465       12432 :             if (nCompressedBytes == 0)
     466             :             {
     467           0 :                 TIFFErrorExtR(tif, module, "Encoder error at scanline %lu",
     468           0 :                               (unsigned long)tif->tif_row);
     469           0 :                 return 0;
     470             :             }
     471             : 
     472       12432 :             tif->tif_rawcc = (tmsize_t)nCompressedBytes;
     473             : 
     474       12432 :             if (!TIFFFlushData1(tif))
     475           0 :                 return 0;
     476             : 
     477       12444 :             return 1;
     478             :         }
     479             :     } while (0);
     480        6098 :     sp->libdeflate_state = 0;
     481             : #endif /* LIBDEFLATE_SUPPORT */
     482             : 
     483        6098 :     sp->stream.next_in = bp;
     484             :     assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
     485             :          we need to simplify this code to reflect a ZLib that is likely updated
     486             :          to deal with 8byte memory sizes, though this code will respond
     487             :          appropriately even before we simplify it */
     488             :     do
     489             :     {
     490        6098 :         uInt avail_in_before = TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)cc);
     491        6098 :         sp->stream.avail_in = avail_in_before;
     492        6098 :         if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK)
     493             :         {
     494           0 :             TIFFErrorExtR(tif, module, "Encoder error: %s", SAFE_MSG(sp));
     495           0 :             return (0);
     496             :         }
     497        6098 :         if (sp->stream.avail_out == 0)
     498             :         {
     499           0 :             tif->tif_rawcc = tif->tif_rawdatasize;
     500           0 :             if (!TIFFFlushData1(tif))
     501           0 :                 return 0;
     502           0 :             sp->stream.next_out = tif->tif_rawdata;
     503           0 :             sp->stream.avail_out =
     504           0 :                 TIFF_CLAMP_UINT64_TO_INT32_MAX((uint64_t)tif->tif_rawdatasize);
     505             :         }
     506        6098 :         cc -= (avail_in_before - sp->stream.avail_in);
     507        6098 :     } while (cc > 0);
     508        6098 :     return (1);
     509             : }
     510             : 
     511             : /*
     512             :  * Finish off an encoded strip by flushing the last
     513             :  * string and tacking on an End Of Information code.
     514             :  */
     515       16540 : static int ZIPPostEncode(TIFF *tif)
     516             : {
     517             :     static const char module[] = "ZIPPostEncode";
     518       16540 :     ZIPState *sp = ZIPEncoderState(tif);
     519             :     int state;
     520             : 
     521             : #if LIBDEFLATE_SUPPORT
     522       16540 :     if (sp->libdeflate_state == 1)
     523       12436 :         return 1;
     524             : #endif
     525             : 
     526        4104 :     sp->stream.avail_in = 0;
     527             :     do
     528             :     {
     529        4104 :         state = deflate(&sp->stream, Z_FINISH);
     530        4098 :         switch (state)
     531             :         {
     532        4098 :             case Z_STREAM_END:
     533             :             case Z_OK:
     534        4098 :                 if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
     535             :                 {
     536        4098 :                     tif->tif_rawcc =
     537        4098 :                         tif->tif_rawdatasize - sp->stream.avail_out;
     538        4098 :                     if (!TIFFFlushData1(tif))
     539           0 :                         return 0;
     540        4098 :                     sp->stream.next_out = tif->tif_rawdata;
     541        4098 :                     sp->stream.avail_out =
     542        4098 :                         (uint64_t)tif->tif_rawdatasize <= 0xFFFFFFFFU
     543        4098 :                             ? (uInt)tif->tif_rawdatasize
     544        4098 :                             : 0xFFFFFFFFU;
     545             :                 }
     546        4098 :                 break;
     547           0 :             default:
     548           0 :                 TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
     549           0 :                 return (0);
     550             :         }
     551        4098 :     } while (state != Z_STREAM_END);
     552        4098 :     return (1);
     553             : }
     554             : 
     555        8264 : static void ZIPCleanup(TIFF *tif)
     556             : {
     557        8264 :     ZIPState *sp = GetZIPState(tif);
     558             : 
     559        8264 :     assert(sp != 0);
     560             : 
     561        8264 :     (void)TIFFPredictorCleanup(tif);
     562             : 
     563        8264 :     tif->tif_tagmethods.vgetfield = sp->vgetparent;
     564        8264 :     tif->tif_tagmethods.vsetfield = sp->vsetparent;
     565             : 
     566        8264 :     if (sp->state & ZSTATE_INIT_ENCODE)
     567             :     {
     568        5729 :         deflateEnd(&sp->stream);
     569        5729 :         sp->state = 0;
     570             :     }
     571        2535 :     else if (sp->state & ZSTATE_INIT_DECODE)
     572             :     {
     573         560 :         inflateEnd(&sp->stream);
     574         560 :         sp->state = 0;
     575             :     }
     576             : 
     577             : #if LIBDEFLATE_SUPPORT
     578        8264 :     if (sp->libdeflate_dec)
     579         505 :         libdeflate_free_decompressor(sp->libdeflate_dec);
     580        8264 :     if (sp->libdeflate_enc)
     581        1640 :         libdeflate_free_compressor(sp->libdeflate_enc);
     582             : #endif
     583             : 
     584        8265 :     _TIFFfreeExt(tif, sp);
     585        8264 :     tif->tif_data = NULL;
     586             : 
     587        8264 :     _TIFFSetDefaultCompressionState(tif);
     588        8265 : }
     589             : 
     590       56329 : static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap)
     591             : {
     592             :     static const char module[] = "ZIPVSetField";
     593       56329 :     ZIPState *sp = GetZIPState(tif);
     594             : 
     595       56329 :     switch (tag)
     596             :     {
     597          48 :         case TIFFTAG_ZIPQUALITY:
     598          48 :             sp->zipquality = (int)va_arg(ap, int);
     599          48 :             if (sp->zipquality < Z_DEFAULT_COMPRESSION ||
     600          48 :                 sp->zipquality > LIBDEFLATE_MAX_COMPRESSION_LEVEL)
     601             :             {
     602           0 :                 TIFFErrorExtR(
     603             :                     tif, module,
     604             :                     "Invalid ZipQuality value. Should be in [-1,%d] range",
     605             :                     LIBDEFLATE_MAX_COMPRESSION_LEVEL);
     606           0 :                 return 0;
     607             :             }
     608             : 
     609          48 :             if (sp->state & ZSTATE_INIT_ENCODE)
     610             :             {
     611           0 :                 int cappedQuality = sp->zipquality;
     612           0 :                 if (cappedQuality > Z_BEST_COMPRESSION)
     613           0 :                     cappedQuality = Z_BEST_COMPRESSION;
     614           0 :                 if (deflateParams(&sp->stream, cappedQuality,
     615             :                                   Z_DEFAULT_STRATEGY) != Z_OK)
     616             :                 {
     617           0 :                     TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
     618           0 :                     return (0);
     619             :                 }
     620             :             }
     621             : 
     622             : #if LIBDEFLATE_SUPPORT
     623          48 :             if (sp->libdeflate_enc)
     624             :             {
     625           0 :                 libdeflate_free_compressor(sp->libdeflate_enc);
     626           0 :                 sp->libdeflate_enc = NULL;
     627             :             }
     628             : #endif
     629             : 
     630          48 :             return (1);
     631             : 
     632        4097 :         case TIFFTAG_DEFLATE_SUBCODEC:
     633        4097 :             sp->subcodec = (int)va_arg(ap, int);
     634        4097 :             if (sp->subcodec != DEFLATE_SUBCODEC_ZLIB &&
     635           0 :                 sp->subcodec != DEFLATE_SUBCODEC_LIBDEFLATE)
     636             :             {
     637           0 :                 TIFFErrorExtR(tif, module, "Invalid DeflateCodec value.");
     638           0 :                 return 0;
     639             :             }
     640             : #if !LIBDEFLATE_SUPPORT
     641             :             if (sp->subcodec == DEFLATE_SUBCODEC_LIBDEFLATE)
     642             :             {
     643             :                 TIFFErrorExtR(tif, module,
     644             :                               "DeflateCodec = DEFLATE_SUBCODEC_LIBDEFLATE "
     645             :                               "unsupported in this build");
     646             :                 return 0;
     647             :             }
     648             : #endif
     649        4097 :             return 1;
     650             : 
     651       52184 :         default:
     652       52184 :             return (*sp->vsetparent)(tif, tag, ap);
     653             :     }
     654             :     /*NOTREACHED*/
     655             : }
     656             : 
     657       56543 : static int ZIPVGetField(TIFF *tif, uint32_t tag, va_list ap)
     658             : {
     659       56543 :     ZIPState *sp = GetZIPState(tif);
     660             : 
     661       56543 :     switch (tag)
     662             :     {
     663           0 :         case TIFFTAG_ZIPQUALITY:
     664           0 :             *va_arg(ap, int *) = sp->zipquality;
     665           0 :             break;
     666             : 
     667           0 :         case TIFFTAG_DEFLATE_SUBCODEC:
     668           0 :             *va_arg(ap, int *) = sp->subcodec;
     669           0 :             break;
     670             : 
     671       56543 :         default:
     672       56543 :             return (*sp->vgetparent)(tif, tag, ap);
     673             :     }
     674           0 :     return (1);
     675             : }
     676             : 
     677             : static const TIFFField zipFields[] = {
     678             :     {TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO, TRUE,
     679             :      FALSE, "", NULL},
     680             :     {TIFFTAG_DEFLATE_SUBCODEC, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO,
     681             :      TRUE, FALSE, "", NULL},
     682             : };
     683             : 
     684       29373 : static void *TIFF_zalloc(void *opaque, unsigned int items, unsigned int size)
     685             : {
     686             :     static const char module[] = "TIFF_zalloc";
     687       29373 :     TIFF *tif = (TIFF *)opaque;
     688             : 
     689       29373 :     if (items > ~(size_t)0 / size)
     690             :     {
     691           0 :         TIFFErrorExtR(tif, module, "Overflow");
     692           0 :         return NULL;
     693             :     }
     694             : 
     695       29373 :     return _TIFFmallocExt(tif, items * size);
     696             : }
     697             : 
     698       29372 : static void TIFF_zfree(void *opaque, void *ptr)
     699             : {
     700       29372 :     _TIFFfreeExt((TIFF *)opaque, ptr);
     701       29370 : }
     702             : 
     703        8266 : int TIFFInitZIP(TIFF *tif, int scheme)
     704             : {
     705             :     static const char module[] = "TIFFInitZIP";
     706             :     ZIPState *sp;
     707             : 
     708        8266 :     assert((scheme == COMPRESSION_DEFLATE) ||
     709             :            (scheme == COMPRESSION_ADOBE_DEFLATE));
     710             : #ifdef NDEBUG
     711             :     (void)scheme;
     712             : #endif
     713             : 
     714             :     /*
     715             :      * Merge codec-specific tag information.
     716             :      */
     717        8266 :     if (!_TIFFMergeFields(tif, zipFields, TIFFArrayCount(zipFields)))
     718             :     {
     719           0 :         TIFFErrorExtR(tif, module,
     720             :                       "Merging Deflate codec-specific tags failed");
     721           0 :         return 0;
     722             :     }
     723             : 
     724             :     /*
     725             :      * Allocate state block so tag methods have storage to record values.
     726             :      */
     727        8266 :     tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, sizeof(ZIPState), 1);
     728        8265 :     if (tif->tif_data == NULL)
     729           0 :         goto bad;
     730        8265 :     sp = GetZIPState(tif);
     731        8265 :     sp->stream.zalloc = TIFF_zalloc;
     732        8265 :     sp->stream.zfree = TIFF_zfree;
     733        8265 :     sp->stream.opaque = tif;
     734        8265 :     sp->stream.data_type = Z_BINARY;
     735             : 
     736             :     /*
     737             :      * Override parent get/set field methods.
     738             :      */
     739        8265 :     sp->vgetparent = tif->tif_tagmethods.vgetfield;
     740        8265 :     tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */
     741        8265 :     sp->vsetparent = tif->tif_tagmethods.vsetfield;
     742        8265 :     tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */
     743             : 
     744             :     /* Default values for codec-specific fields */
     745        8265 :     sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */
     746        8265 :     sp->state = 0;
     747             : #if LIBDEFLATE_SUPPORT
     748        8265 :     sp->subcodec = DEFLATE_SUBCODEC_LIBDEFLATE;
     749             : #else
     750             :     sp->subcodec = DEFLATE_SUBCODEC_ZLIB;
     751             : #endif
     752             : 
     753             :     /*
     754             :      * Install codec methods.
     755             :      */
     756        8265 :     tif->tif_fixuptags = ZIPFixupTags;
     757        8265 :     tif->tif_setupdecode = ZIPSetupDecode;
     758        8265 :     tif->tif_predecode = ZIPPreDecode;
     759        8265 :     tif->tif_decoderow = ZIPDecode;
     760        8265 :     tif->tif_decodestrip = ZIPDecode;
     761        8265 :     tif->tif_decodetile = ZIPDecode;
     762        8265 :     tif->tif_setupencode = ZIPSetupEncode;
     763        8265 :     tif->tif_preencode = ZIPPreEncode;
     764        8265 :     tif->tif_postencode = ZIPPostEncode;
     765        8265 :     tif->tif_encoderow = ZIPEncode;
     766        8265 :     tif->tif_encodestrip = ZIPEncode;
     767        8265 :     tif->tif_encodetile = ZIPEncode;
     768        8265 :     tif->tif_cleanup = ZIPCleanup;
     769             :     /*
     770             :      * Setup predictor setup.
     771             :      */
     772        8265 :     (void)TIFFPredictorInit(tif);
     773        8266 :     return (1);
     774           0 : bad:
     775           0 :     TIFFErrorExtR(tif, module, "No space for ZIP state block");
     776           0 :     return (0);
     777             : }
     778             : #endif /* ZIP_SUPPORT */

Generated by: LCOV version 1.14