LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_zip.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 240 314 76.4 %
Date: 2024-11-21 22:18:42 Functions: 12 12 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        1962 : static int ZIPFixupTags(TIFF *tif)
      96             : {
      97             :     (void)tif;
      98        1962 :     return (1);
      99             : }
     100             : 
     101         460 : static int ZIPSetupDecode(TIFF *tif)
     102             : {
     103             :     static const char module[] = "ZIPSetupDecode";
     104         460 :     ZIPState *sp = ZIPDecoderState(tif);
     105             : 
     106         460 :     assert(sp != NULL);
     107             : 
     108             :     /* if we were last encoding, terminate this mode */
     109         460 :     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         920 :     if ((sp->state & ZSTATE_INIT_DECODE) == 0 &&
     119         461 :         inflateInit(&sp->stream) != Z_OK)
     120             :     {
     121           0 :         TIFFErrorExtR(tif, module, "%s", SAFE_MSG(sp));
     122           0 :         return (0);
     123             :     }
     124             :     else
     125             :     {
     126         459 :         sp->state |= ZSTATE_INIT_DECODE;
     127         459 :         return (1);
     128             :     }
     129             : }
     130             : 
     131             : /*
     132             :  * Setup state for decoding a strip.
     133             :  */
     134        3072 : static int ZIPPreDecode(TIFF *tif, uint16_t s)
     135             : {
     136        3072 :     ZIPState *sp = ZIPDecoderState(tif);
     137             : 
     138             :     (void)s;
     139        3072 :     assert(sp != NULL);
     140             : 
     141        3072 :     if ((sp->state & ZSTATE_INIT_DECODE) == 0)
     142          15 :         tif->tif_setupdecode(tif);
     143             : 
     144             : #if LIBDEFLATE_SUPPORT
     145        3073 :     sp->libdeflate_state = -1;
     146             : #endif
     147        3073 :     sp->stream.next_in = tif->tif_rawdata;
     148             :     assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
     149             :          we need to simplify this code to reflect a ZLib that is likely updated
     150             :          to deal with 8byte memory sizes, though this code will respond
     151             :          appropriately even before we simplify it */
     152        6146 :     sp->stream.avail_in = (uint64_t)tif->tif_rawcc < 0xFFFFFFFFU
     153        3073 :                               ? (uInt)tif->tif_rawcc
     154        3073 :                               : 0xFFFFFFFFU;
     155        3073 :     if (inflateReset(&sp->stream) == Z_OK)
     156             :     {
     157        3072 :         sp->read_error = 0;
     158        3072 :         return 1;
     159             :     }
     160           1 :     return 0;
     161             : }
     162             : 
     163        5072 : static int ZIPDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
     164             : {
     165             :     static const char module[] = "ZIPDecode";
     166        5072 :     ZIPState *sp = ZIPDecoderState(tif);
     167             : 
     168             :     (void)s;
     169        5072 :     assert(sp != NULL);
     170        5072 :     assert(sp->state == ZSTATE_INIT_DECODE);
     171             : 
     172        5072 :     if (sp->read_error)
     173             :     {
     174           0 :         memset(op, 0, (size_t)occ);
     175           0 :         TIFFErrorExtR(tif, module,
     176             :                       "ZIPDecode: Scanline %" PRIu32 " cannot be read due to "
     177             :                       "previous error",
     178             :                       tif->tif_row);
     179           0 :         return 0;
     180             :     }
     181             : 
     182             : #if LIBDEFLATE_SUPPORT
     183        5072 :     if (sp->libdeflate_state == 1)
     184           0 :         return 0;
     185             : 
     186             :     /* If we have libdeflate support and we are asked to read a whole */
     187             :     /* strip/tile, then go for using it */
     188             :     do
     189             :     {
     190        5072 :         TIFFDirectory *td = &tif->tif_dir;
     191             : 
     192        5072 :         if (sp->libdeflate_state == 0)
     193        2000 :             break;
     194        3072 :         if (sp->subcodec == DEFLATE_SUBCODEC_ZLIB)
     195           0 :             break;
     196             : 
     197             :         /* Check if we are in the situation where we can use libdeflate */
     198        3072 :         if (isTiled(tif))
     199             :         {
     200         931 :             if (TIFFTileSize64(tif) != (uint64_t)occ)
     201         144 :                 break;
     202             :         }
     203             :         else
     204             :         {
     205        2141 :             uint32_t strip_height = td->td_imagelength - tif->tif_row;
     206        2141 :             if (strip_height > td->td_rowsperstrip)
     207        1484 :                 strip_height = td->td_rowsperstrip;
     208        2141 :             if (TIFFVStripSize64(tif, strip_height) != (uint64_t)occ)
     209           2 :                 break;
     210             :         }
     211             : 
     212             :         /* Check for overflow */
     213             :         if ((size_t)tif->tif_rawcc != (uint64_t)tif->tif_rawcc)
     214             :             break;
     215             :         if ((size_t)occ != (uint64_t)occ)
     216             :             break;
     217             : 
     218             :         /* Go for decompression using libdeflate */
     219             :         {
     220             :             enum libdeflate_result res;
     221        2926 :             if (sp->libdeflate_dec == NULL)
     222             :             {
     223         400 :                 sp->libdeflate_dec = libdeflate_alloc_decompressor();
     224         401 :                 if (sp->libdeflate_dec == NULL)
     225             :                 {
     226           0 :                     break;
     227             :                 }
     228             :             }
     229             : 
     230        2927 :             sp->libdeflate_state = 1;
     231             : 
     232        2927 :             res = libdeflate_zlib_decompress(sp->libdeflate_dec, tif->tif_rawcp,
     233        2927 :                                              (size_t)tif->tif_rawcc, op,
     234             :                                              (size_t)occ, NULL);
     235             : 
     236        2927 :             tif->tif_rawcp += tif->tif_rawcc;
     237        2927 :             tif->tif_rawcc = 0;
     238             : 
     239             :             /* We accept LIBDEFLATE_INSUFFICIENT_SPACE has a return */
     240             :             /* There are odd files in the wild where the last strip, when */
     241             :             /* it is smaller in height than td_rowsperstrip, actually contains
     242             :              */
     243             :             /* data for td_rowsperstrip lines. Just ignore that silently. */
     244        2927 :             if (res != LIBDEFLATE_SUCCESS &&
     245             :                 res != LIBDEFLATE_INSUFFICIENT_SPACE)
     246             :             {
     247           0 :                 memset(op, 0, (size_t)occ);
     248           0 :                 TIFFErrorExtR(tif, module, "Decoding error at scanline %lu",
     249           0 :                               (unsigned long)tif->tif_row);
     250           0 :                 sp->read_error = 1;
     251           0 :                 return 0;
     252             :             }
     253             : 
     254        2927 :             return 1;
     255             :         }
     256             :     } while (0);
     257        2146 :     sp->libdeflate_state = 0;
     258             : #endif /* LIBDEFLATE_SUPPORT */
     259             : 
     260        2146 :     sp->stream.next_in = tif->tif_rawcp;
     261             : 
     262        2146 :     sp->stream.next_out = op;
     263             :     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
     264             :          we need to simplify this code to reflect a ZLib that is likely updated
     265             :          to deal with 8byte memory sizes, though this code will respond
     266             :          appropriately even before we simplify it */
     267             :     do
     268             :     {
     269             :         int state;
     270        4292 :         uInt avail_in_before = (uint64_t)tif->tif_rawcc <= 0xFFFFFFFFU
     271        2146 :                                    ? (uInt)tif->tif_rawcc
     272        2146 :                                    : 0xFFFFFFFFU;
     273        2146 :         uInt avail_out_before =
     274        2146 :             (uint64_t)occ < 0xFFFFFFFFU ? (uInt)occ : 0xFFFFFFFFU;
     275        2146 :         sp->stream.avail_in = avail_in_before;
     276        2146 :         sp->stream.avail_out = avail_out_before;
     277             :         /* coverity[overrun-buffer-arg] */
     278        2146 :         state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
     279        2146 :         tif->tif_rawcc -= (avail_in_before - sp->stream.avail_in);
     280        2146 :         occ -= (avail_out_before - sp->stream.avail_out);
     281        2146 :         if (state == Z_STREAM_END)
     282           1 :             break;
     283        2145 :         if (state == Z_DATA_ERROR)
     284             :         {
     285           1 :             memset(sp->stream.next_out, 0, sp->stream.avail_out);
     286           1 :             TIFFErrorExtR(tif, module, "Decoding error at scanline %lu, %s",
     287           2 :                           (unsigned long)tif->tif_row, SAFE_MSG(sp));
     288           1 :             sp->read_error = 1;
     289           1 :             return (0);
     290             :         }
     291        2144 :         if (state != Z_OK)
     292             :         {
     293           0 :             memset(sp->stream.next_out, 0, sp->stream.avail_out);
     294           0 :             TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
     295           0 :             sp->read_error = 1;
     296           0 :             return (0);
     297             :         }
     298        2144 :     } while (occ > 0);
     299        2145 :     if (occ != 0)
     300             :     {
     301           0 :         TIFFErrorExtR(tif, module,
     302             :                       "Not enough data at scanline %lu (short %" PRIu64
     303             :                       " bytes)",
     304           0 :                       (unsigned long)tif->tif_row, (uint64_t)occ);
     305           0 :         memset(sp->stream.next_out, 0, sp->stream.avail_out);
     306           0 :         sp->read_error = 1;
     307           0 :         return (0);
     308             :     }
     309             : 
     310        2145 :     tif->tif_rawcp = sp->stream.next_in;
     311             : 
     312        2145 :     return (1);
     313             : }
     314             : 
     315        5631 : static int ZIPSetupEncode(TIFF *tif)
     316             : {
     317             :     static const char module[] = "ZIPSetupEncode";
     318        5631 :     ZIPState *sp = ZIPEncoderState(tif);
     319             :     int cappedQuality;
     320             : 
     321        5631 :     assert(sp != NULL);
     322        5631 :     if (sp->state & ZSTATE_INIT_DECODE)
     323             :     {
     324           8 :         inflateEnd(&sp->stream);
     325           8 :         sp->state = 0;
     326             :     }
     327             : 
     328        5631 :     cappedQuality = sp->zipquality;
     329        5631 :     if (cappedQuality > Z_BEST_COMPRESSION)
     330           0 :         cappedQuality = Z_BEST_COMPRESSION;
     331             : 
     332        5631 :     if (deflateInit(&sp->stream, cappedQuality) != Z_OK)
     333             :     {
     334           0 :         TIFFErrorExtR(tif, module, "%s", SAFE_MSG(sp));
     335           0 :         return (0);
     336             :     }
     337             :     else
     338             :     {
     339        5631 :         sp->state |= ZSTATE_INIT_ENCODE;
     340        5631 :         return (1);
     341             :     }
     342             : }
     343             : 
     344             : /*
     345             :  * Reset encoding state at the start of a strip.
     346             :  */
     347       13157 : static int ZIPPreEncode(TIFF *tif, uint16_t s)
     348             : {
     349       13157 :     ZIPState *sp = ZIPEncoderState(tif);
     350             : 
     351             :     (void)s;
     352       13157 :     assert(sp != NULL);
     353       13157 :     if (sp->state != ZSTATE_INIT_ENCODE)
     354           8 :         tif->tif_setupencode(tif);
     355             : 
     356             : #if LIBDEFLATE_SUPPORT
     357       13146 :     sp->libdeflate_state = -1;
     358             : #endif
     359       13146 :     sp->stream.next_out = tif->tif_rawdata;
     360             :     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
     361             :          we need to simplify this code to reflect a ZLib that is likely updated
     362             :          to deal with 8byte memory sizes, though this code will respond
     363             :          appropriately even before we simplify it */
     364       26292 :     sp->stream.avail_out = (uint64_t)tif->tif_rawdatasize <= 0xFFFFFFFFU
     365       13144 :                                ? (uInt)tif->tif_rawdatasize
     366       13146 :                                : 0xFFFFFFFFU;
     367       13146 :     return (deflateReset(&sp->stream) == Z_OK);
     368             : }
     369             : 
     370             : /*
     371             :  * Encode a chunk of pixels.
     372             :  */
     373       15157 : static int ZIPEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
     374             : {
     375             :     static const char module[] = "ZIPEncode";
     376       15157 :     ZIPState *sp = ZIPEncoderState(tif);
     377             : 
     378       15157 :     assert(sp != NULL);
     379       15157 :     assert(sp->state == ZSTATE_INIT_ENCODE);
     380             : 
     381             :     (void)s;
     382             : 
     383             : #if LIBDEFLATE_SUPPORT
     384       15157 :     if (sp->libdeflate_state == 1)
     385           0 :         return 0;
     386             : 
     387             :     /* If we have libdeflate support and we are asked to write a whole */
     388             :     /* strip/tile, then go for using it */
     389             :     do
     390             :     {
     391       15157 :         TIFFDirectory *td = &tif->tif_dir;
     392             : 
     393       15157 :         if (sp->libdeflate_state == 0)
     394        2000 :             break;
     395       13157 :         if (sp->subcodec == DEFLATE_SUBCODEC_ZLIB)
     396        4097 :             break;
     397             : 
     398             :         /* Libdeflate does not support the 0-compression level */
     399        9060 :         if (sp->zipquality == Z_NO_COMPRESSION)
     400           0 :             break;
     401             : 
     402             :         /* Check if we are in the situation where we can use libdeflate */
     403        9060 :         if (isTiled(tif))
     404             :         {
     405        5682 :             if (TIFFTileSize64(tif) != (uint64_t)cc)
     406           0 :                 break;
     407             :         }
     408             :         else
     409             :         {
     410        3378 :             uint32_t strip_height = td->td_imagelength - tif->tif_row;
     411        3378 :             if (strip_height > td->td_rowsperstrip)
     412        2018 :                 strip_height = td->td_rowsperstrip;
     413        3378 :             if (TIFFVStripSize64(tif, strip_height) != (uint64_t)cc)
     414           1 :                 break;
     415             :         }
     416             : 
     417             :         /* Check for overflow */
     418             :         if ((size_t)tif->tif_rawdatasize != (uint64_t)tif->tif_rawdatasize)
     419             :             break;
     420             :         if ((size_t)cc != (uint64_t)cc)
     421             :             break;
     422             : 
     423             :         /* Go for compression using libdeflate */
     424             :         {
     425             :             size_t nCompressedBytes;
     426        9060 :             if (sp->libdeflate_enc == NULL)
     427             :             {
     428             :                 /* To get results as good as zlib, we asked for an extra */
     429             :                 /* level of compression */
     430        1528 :                 sp->libdeflate_enc = libdeflate_alloc_compressor(
     431        1528 :                     sp->zipquality == Z_DEFAULT_COMPRESSION ? 7
     432          12 :                     : sp->zipquality >= 6 && sp->zipquality <= 9
     433          12 :                         ? sp->zipquality + 1
     434          32 :                         : sp->zipquality);
     435        1526 :                 if (sp->libdeflate_enc == NULL)
     436             :                 {
     437           0 :                     TIFFErrorExtR(tif, module, "Cannot allocate compressor");
     438           0 :                     break;
     439             :                 }
     440             :             }
     441             : 
     442             :             /* Make sure the output buffer is large enough for the worse case.
     443             :              */
     444             :             /* In TIFFWriteBufferSetup(), when libtiff allocates the buffer */
     445             :             /* we've taken a 10% margin over the uncompressed size, which should
     446             :              */
     447             :             /* be large enough even for the the worse case scenario. */
     448        9058 :             if (libdeflate_zlib_compress_bound(sp->libdeflate_enc, (size_t)cc) >
     449        9060 :                 (size_t)tif->tif_rawdatasize)
     450             :             {
     451           0 :                 break;
     452             :             }
     453             : 
     454        9060 :             sp->libdeflate_state = 1;
     455        9060 :             nCompressedBytes = libdeflate_zlib_compress(
     456        9060 :                 sp->libdeflate_enc, bp, (size_t)cc, tif->tif_rawdata,
     457        9060 :                 (size_t)tif->tif_rawdatasize);
     458             : 
     459        9056 :             if (nCompressedBytes == 0)
     460             :             {
     461           0 :                 TIFFErrorExtR(tif, module, "Encoder error at scanline %lu",
     462           0 :                               (unsigned long)tif->tif_row);
     463           0 :                 return 0;
     464             :             }
     465             : 
     466        9056 :             tif->tif_rawcc = nCompressedBytes;
     467             : 
     468        9056 :             if (!TIFFFlushData1(tif))
     469           0 :                 return 0;
     470             : 
     471        9058 :             return 1;
     472             :         }
     473             :     } while (0);
     474        6098 :     sp->libdeflate_state = 0;
     475             : #endif /* LIBDEFLATE_SUPPORT */
     476             : 
     477        6098 :     sp->stream.next_in = bp;
     478             :     assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
     479             :          we need to simplify this code to reflect a ZLib that is likely updated
     480             :          to deal with 8byte memory sizes, though this code will respond
     481             :          appropriately even before we simplify it */
     482             :     do
     483             :     {
     484        6098 :         uInt avail_in_before =
     485        6098 :             (uint64_t)cc <= 0xFFFFFFFFU ? (uInt)cc : 0xFFFFFFFFU;
     486        6098 :         sp->stream.avail_in = avail_in_before;
     487             :         /* coverity[overrun-buffer-arg] */
     488        6098 :         if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK)
     489             :         {
     490           0 :             TIFFErrorExtR(tif, module, "Encoder error: %s", SAFE_MSG(sp));
     491           0 :             return (0);
     492             :         }
     493        6098 :         if (sp->stream.avail_out == 0)
     494             :         {
     495           0 :             tif->tif_rawcc = tif->tif_rawdatasize;
     496           0 :             if (!TIFFFlushData1(tif))
     497           0 :                 return 0;
     498           0 :             sp->stream.next_out = tif->tif_rawdata;
     499           0 :             sp->stream.avail_out = (uint64_t)tif->tif_rawdatasize <= 0xFFFFFFFFU
     500           0 :                                        ? (uInt)tif->tif_rawdatasize
     501           0 :                                        : 0xFFFFFFFFU;
     502             :         }
     503        6098 :         cc -= (avail_in_before - sp->stream.avail_in);
     504        6098 :     } while (cc > 0);
     505        6098 :     return (1);
     506             : }
     507             : 
     508             : /*
     509             :  * Finish off an encoded strip by flushing the last
     510             :  * string and tacking on an End Of Information code.
     511             :  */
     512       13156 : static int ZIPPostEncode(TIFF *tif)
     513             : {
     514             :     static const char module[] = "ZIPPostEncode";
     515       13156 :     ZIPState *sp = ZIPEncoderState(tif);
     516             :     int state;
     517             : 
     518             : #if LIBDEFLATE_SUPPORT
     519       13156 :     if (sp->libdeflate_state == 1)
     520        9056 :         return 1;
     521             : #endif
     522             : 
     523        4100 :     sp->stream.avail_in = 0;
     524             :     do
     525             :     {
     526        4100 :         state = deflate(&sp->stream, Z_FINISH);
     527        4098 :         switch (state)
     528             :         {
     529        4098 :             case Z_STREAM_END:
     530             :             case Z_OK:
     531        4098 :                 if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
     532             :                 {
     533        4098 :                     tif->tif_rawcc =
     534        4098 :                         tif->tif_rawdatasize - sp->stream.avail_out;
     535        4098 :                     if (!TIFFFlushData1(tif))
     536           0 :                         return 0;
     537        4098 :                     sp->stream.next_out = tif->tif_rawdata;
     538        4098 :                     sp->stream.avail_out =
     539        4098 :                         (uint64_t)tif->tif_rawdatasize <= 0xFFFFFFFFU
     540        4098 :                             ? (uInt)tif->tif_rawdatasize
     541        4098 :                             : 0xFFFFFFFFU;
     542             :                 }
     543        4098 :                 break;
     544           0 :             default:
     545           0 :                 TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
     546           0 :                 return (0);
     547             :         }
     548        4098 :     } while (state != Z_STREAM_END);
     549        4098 :     return (1);
     550             : }
     551             : 
     552        7683 : static void ZIPCleanup(TIFF *tif)
     553             : {
     554        7683 :     ZIPState *sp = GetZIPState(tif);
     555             : 
     556        7683 :     assert(sp != 0);
     557             : 
     558        7683 :     (void)TIFFPredictorCleanup(tif);
     559             : 
     560        7684 :     tif->tif_tagmethods.vgetfield = sp->vgetparent;
     561        7684 :     tif->tif_tagmethods.vsetfield = sp->vsetparent;
     562             : 
     563        7684 :     if (sp->state & ZSTATE_INIT_ENCODE)
     564             :     {
     565        5615 :         deflateEnd(&sp->stream);
     566        5614 :         sp->state = 0;
     567             :     }
     568        2069 :     else if (sp->state & ZSTATE_INIT_DECODE)
     569             :     {
     570         453 :         inflateEnd(&sp->stream);
     571         453 :         sp->state = 0;
     572             :     }
     573             : 
     574             : #if LIBDEFLATE_SUPPORT
     575        7683 :     if (sp->libdeflate_dec)
     576         401 :         libdeflate_free_decompressor(sp->libdeflate_dec);
     577        7683 :     if (sp->libdeflate_enc)
     578        1527 :         libdeflate_free_compressor(sp->libdeflate_enc);
     579             : #endif
     580             : 
     581        7683 :     _TIFFfreeExt(tif, sp);
     582        7683 :     tif->tif_data = NULL;
     583             : 
     584        7683 :     _TIFFSetDefaultCompressionState(tif);
     585        7684 : }
     586             : 
     587       51311 : static int ZIPVSetField(TIFF *tif, uint32_t tag, va_list ap)
     588             : {
     589             :     static const char module[] = "ZIPVSetField";
     590       51311 :     ZIPState *sp = GetZIPState(tif);
     591             : 
     592       51311 :     switch (tag)
     593             :     {
     594          48 :         case TIFFTAG_ZIPQUALITY:
     595          48 :             sp->zipquality = (int)va_arg(ap, int);
     596          48 :             if (sp->zipquality < Z_DEFAULT_COMPRESSION ||
     597          48 :                 sp->zipquality > LIBDEFLATE_MAX_COMPRESSION_LEVEL)
     598             :             {
     599           0 :                 TIFFErrorExtR(
     600             :                     tif, module,
     601             :                     "Invalid ZipQuality value. Should be in [-1,%d] range",
     602             :                     LIBDEFLATE_MAX_COMPRESSION_LEVEL);
     603           0 :                 return 0;
     604             :             }
     605             : 
     606          48 :             if (sp->state & ZSTATE_INIT_ENCODE)
     607             :             {
     608           0 :                 int cappedQuality = sp->zipquality;
     609           0 :                 if (cappedQuality > Z_BEST_COMPRESSION)
     610           0 :                     cappedQuality = Z_BEST_COMPRESSION;
     611           0 :                 if (deflateParams(&sp->stream, cappedQuality,
     612             :                                   Z_DEFAULT_STRATEGY) != Z_OK)
     613             :                 {
     614           0 :                     TIFFErrorExtR(tif, module, "ZLib error: %s", SAFE_MSG(sp));
     615           0 :                     return (0);
     616             :                 }
     617             :             }
     618             : 
     619             : #if LIBDEFLATE_SUPPORT
     620          48 :             if (sp->libdeflate_enc)
     621             :             {
     622           0 :                 libdeflate_free_compressor(sp->libdeflate_enc);
     623           0 :                 sp->libdeflate_enc = NULL;
     624             :             }
     625             : #endif
     626             : 
     627          48 :             return (1);
     628             : 
     629        4097 :         case TIFFTAG_DEFLATE_SUBCODEC:
     630        4097 :             sp->subcodec = (int)va_arg(ap, int);
     631        4097 :             if (sp->subcodec != DEFLATE_SUBCODEC_ZLIB &&
     632           0 :                 sp->subcodec != DEFLATE_SUBCODEC_LIBDEFLATE)
     633             :             {
     634           0 :                 TIFFErrorExtR(tif, module, "Invalid DeflateCodec value.");
     635           0 :                 return 0;
     636             :             }
     637             : #if !LIBDEFLATE_SUPPORT
     638             :             if (sp->subcodec == DEFLATE_SUBCODEC_LIBDEFLATE)
     639             :             {
     640             :                 TIFFErrorExtR(tif, module,
     641             :                               "DeflateCodec = DEFLATE_SUBCODEC_LIBDEFLATE "
     642             :                               "unsupported in this build");
     643             :                 return 0;
     644             :             }
     645             : #endif
     646        4097 :             return 1;
     647             : 
     648       47166 :         default:
     649       47166 :             return (*sp->vsetparent)(tif, tag, ap);
     650             :     }
     651             :     /*NOTREACHED*/
     652             : }
     653             : 
     654       48596 : static int ZIPVGetField(TIFF *tif, uint32_t tag, va_list ap)
     655             : {
     656       48596 :     ZIPState *sp = GetZIPState(tif);
     657             : 
     658       48596 :     switch (tag)
     659             :     {
     660           0 :         case TIFFTAG_ZIPQUALITY:
     661           0 :             *va_arg(ap, int *) = sp->zipquality;
     662           0 :             break;
     663             : 
     664           0 :         case TIFFTAG_DEFLATE_SUBCODEC:
     665           0 :             *va_arg(ap, int *) = sp->subcodec;
     666           0 :             break;
     667             : 
     668       48596 :         default:
     669       48596 :             return (*sp->vgetparent)(tif, tag, ap);
     670             :     }
     671           0 :     return (1);
     672             : }
     673             : 
     674             : static const TIFFField zipFields[] = {
     675             :     {TIFFTAG_ZIPQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
     676             :      TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "", NULL},
     677             :     {TIFFTAG_DEFLATE_SUBCODEC, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
     678             :      TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "", NULL},
     679             : };
     680             : 
     681        7685 : int TIFFInitZIP(TIFF *tif, int scheme)
     682             : {
     683             :     static const char module[] = "TIFFInitZIP";
     684             :     ZIPState *sp;
     685             : 
     686        7685 :     assert((scheme == COMPRESSION_DEFLATE) ||
     687             :            (scheme == COMPRESSION_ADOBE_DEFLATE));
     688             : #ifdef NDEBUG
     689             :     (void)scheme;
     690             : #endif
     691             : 
     692             :     /*
     693             :      * Merge codec-specific tag information.
     694             :      */
     695        7685 :     if (!_TIFFMergeFields(tif, zipFields, TIFFArrayCount(zipFields)))
     696             :     {
     697           0 :         TIFFErrorExtR(tif, module,
     698             :                       "Merging Deflate codec-specific tags failed");
     699           0 :         return 0;
     700             :     }
     701             : 
     702             :     /*
     703             :      * Allocate state block so tag methods have storage to record values.
     704             :      */
     705        7685 :     tif->tif_data = (uint8_t *)_TIFFcallocExt(tif, sizeof(ZIPState), 1);
     706        7685 :     if (tif->tif_data == NULL)
     707           0 :         goto bad;
     708        7685 :     sp = GetZIPState(tif);
     709        7685 :     sp->stream.zalloc = NULL;
     710        7685 :     sp->stream.zfree = NULL;
     711        7685 :     sp->stream.opaque = NULL;
     712        7685 :     sp->stream.data_type = Z_BINARY;
     713             : 
     714             :     /*
     715             :      * Override parent get/set field methods.
     716             :      */
     717        7685 :     sp->vgetparent = tif->tif_tagmethods.vgetfield;
     718        7685 :     tif->tif_tagmethods.vgetfield = ZIPVGetField; /* hook for codec tags */
     719        7685 :     sp->vsetparent = tif->tif_tagmethods.vsetfield;
     720        7685 :     tif->tif_tagmethods.vsetfield = ZIPVSetField; /* hook for codec tags */
     721             : 
     722             :     /* Default values for codec-specific fields */
     723        7685 :     sp->zipquality = Z_DEFAULT_COMPRESSION; /* default comp. level */
     724        7685 :     sp->state = 0;
     725             : #if LIBDEFLATE_SUPPORT
     726        7685 :     sp->subcodec = DEFLATE_SUBCODEC_LIBDEFLATE;
     727             : #else
     728             :     sp->subcodec = DEFLATE_SUBCODEC_ZLIB;
     729             : #endif
     730             : 
     731             :     /*
     732             :      * Install codec methods.
     733             :      */
     734        7685 :     tif->tif_fixuptags = ZIPFixupTags;
     735        7685 :     tif->tif_setupdecode = ZIPSetupDecode;
     736        7685 :     tif->tif_predecode = ZIPPreDecode;
     737        7685 :     tif->tif_decoderow = ZIPDecode;
     738        7685 :     tif->tif_decodestrip = ZIPDecode;
     739        7685 :     tif->tif_decodetile = ZIPDecode;
     740        7685 :     tif->tif_setupencode = ZIPSetupEncode;
     741        7685 :     tif->tif_preencode = ZIPPreEncode;
     742        7685 :     tif->tif_postencode = ZIPPostEncode;
     743        7685 :     tif->tif_encoderow = ZIPEncode;
     744        7685 :     tif->tif_encodestrip = ZIPEncode;
     745        7685 :     tif->tif_encodetile = ZIPEncode;
     746        7685 :     tif->tif_cleanup = ZIPCleanup;
     747             :     /*
     748             :      * Setup predictor setup.
     749             :      */
     750        7685 :     (void)TIFFPredictorInit(tif);
     751        7685 :     return (1);
     752           0 : bad:
     753           0 :     TIFFErrorExtR(tif, module, "No space for ZIP state block");
     754           0 :     return (0);
     755             : }
     756             : #endif /* ZIP_SUPPORT */

Generated by: LCOV version 1.14