[LIBTIFF]
[reactos.git] / reactos / dll / 3rdparty / libtiff / tif_pixarlog.c
index 4e61445..b0756d0 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: tif_pixarlog.c,v 1.48 2016-09-23 22:12:18 erouault Exp $ */
+/* $Id: tif_pixarlog.c,v 1.53 2017-05-17 09:53:06 erouault Exp $ */
 
 /*
  * Copyright (c) 1996-1997 Sam Leffler
@@ -637,29 +637,27 @@ PixarLogGuessDataFmt(TIFFDirectory *td)
        return guess;
 }
 
+#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
+#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
+
 static tmsize_t
 multiply_ms(tmsize_t m1, tmsize_t m2)
 {
-       tmsize_t bytes = m1 * m2;
-
-       if (m1 && bytes / m1 != m2)
-               bytes = 0;
-
-       return bytes;
+        if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 )
+            return 0;
+        return m1 * m2;
 }
 
 static tmsize_t
 add_ms(tmsize_t m1, tmsize_t m2)
 {
-       tmsize_t bytes = m1 + m2;
-
        /* if either input is zero, assume overflow already occurred */
        if (m1 == 0 || m2 == 0)
-               bytes = 0;
-       else if (bytes <= m1 || bytes <= m2)
-               bytes = 0;
+               return 0;
+       else if (m1 > TIFF_TMSIZE_T_MAX - m2)
+               return 0;
 
-       return bytes;
+       return m1 + m2;
 }
 
 static int
@@ -679,6 +677,12 @@ PixarLogSetupDecode(TIFF* tif)
 
        assert(sp != NULL);
 
+       /* This function can possibly be called several times by */
+       /* PredictorSetupDecode() if this function succeeds but */
+       /* PredictorSetup() fails */
+       if( (sp->state & PLSTATE_INIT) != 0 )
+               return 1;
+
        /* Make sure no byte swapping happens on the data
         * after decompression. */
        tif->tif_postdecode = _TIFFNoPostDecode;  
@@ -700,6 +704,9 @@ PixarLogSetupDecode(TIFF* tif)
        if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
                sp->user_datafmt = PixarLogGuessDataFmt(td);
        if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
+                _TIFFfree(sp->tbuf);
+                sp->tbuf = NULL;
+                sp->tbuf_size = 0;
                TIFFErrorExt(tif->tif_clientdata, module,
                        "PixarLog compression can't handle bits depth/data format combination (depth: %d)", 
                        td->td_bitspersample);
@@ -707,6 +714,9 @@ PixarLogSetupDecode(TIFF* tif)
        }
 
        if (inflateInit(&sp->stream) != Z_OK) {
+                _TIFFfree(sp->tbuf);
+                sp->tbuf = NULL;
+                sp->tbuf_size = 0;
                TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)");
                return (0);
        } else {
@@ -775,6 +785,10 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
 
        (void) s;
        assert(sp != NULL);
+
+        sp->stream.next_in = tif->tif_rawcp;
+       sp->stream.avail_in = (uInt) tif->tif_rawcc;
+
        sp->stream.next_out = (unsigned char *) sp->tbuf;
        assert(sizeof(sp->stream.avail_out)==4);  /* if this assert gets raised,
            we need to simplify this code to reflect a ZLib that is likely updated
@@ -820,6 +834,9 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
                return (0);
        }
 
+        tif->tif_rawcp = sp->stream.next_in;
+        tif->tif_rawcc = sp->stream.avail_in;
+
        up = sp->tbuf;
        /* Swap bytes in the data if from a different endian machine. */
        if (tif->tif_flags & TIFF_SWAB)
@@ -1234,8 +1251,10 @@ PixarLogPostEncode(TIFF* tif)
 static void
 PixarLogClose(TIFF* tif)
 {
+        PixarLogState* sp = (PixarLogState*) tif->tif_data;
        TIFFDirectory *td = &tif->tif_dir;
 
+       assert(sp != 0);
        /* In a really sneaky (and really incorrect, and untruthful, and
         * troublesome, and error-prone) maneuver that completely goes against
         * the spirit of TIFF, and breaks TIFF, on close, we covertly
@@ -1244,8 +1263,19 @@ PixarLogClose(TIFF* tif)
         * readers that don't know about PixarLog, or how to set
         * the PIXARLOGDATFMT pseudo-tag.
         */
-       td->td_bitspersample = 8;
-       td->td_sampleformat = SAMPLEFORMAT_UINT;
+
+        if (sp->state&PLSTATE_INIT) {
+            /* We test the state to avoid an issue such as in
+             * http://bugzilla.maptools.org/show_bug.cgi?id=2604
+             * What appends in that case is that the bitspersample is 1 and
+             * a TransferFunction is set. The size of the TransferFunction
+             * depends on 1<<bitspersample. So if we increase it, an access
+             * out of the buffer will happen at directory flushing.
+             * Another option would be to clear those targs. 
+             */
+            td->td_bitspersample = 8;
+            td->td_sampleformat = SAMPLEFORMAT_UINT;
+        }
 }
 
 static void