[LIBTIFF] Update to version 4.1.0. CORE-16550
authorThomas Faber <thomas.faber@reactos.org>
Sun, 8 Dec 2019 11:36:30 +0000 (12:36 +0100)
committerThomas Faber <thomas.faber@reactos.org>
Sun, 8 Dec 2019 15:49:57 +0000 (16:49 +0100)
28 files changed:
dll/3rdparty/libtiff/mkg3states.c
dll/3rdparty/libtiff/tif_aux.c
dll/3rdparty/libtiff/tif_dir.c
dll/3rdparty/libtiff/tif_dirread.c
dll/3rdparty/libtiff/tif_dirwrite.c
dll/3rdparty/libtiff/tif_flush.c
dll/3rdparty/libtiff/tif_getimage.c
dll/3rdparty/libtiff/tif_jpeg.c
dll/3rdparty/libtiff/tif_luv.c
dll/3rdparty/libtiff/tif_lzw.c
dll/3rdparty/libtiff/tif_ojpeg.c
dll/3rdparty/libtiff/tif_open.c
dll/3rdparty/libtiff/tif_packbits.c
dll/3rdparty/libtiff/tif_pixarlog.c
dll/3rdparty/libtiff/tif_print.c
dll/3rdparty/libtiff/tif_read.c
dll/3rdparty/libtiff/tif_strip.c
dll/3rdparty/libtiff/tif_thunder.c
dll/3rdparty/libtiff/tif_tile.c
dll/3rdparty/libtiff/tif_version.c
dll/3rdparty/libtiff/tif_webp.c
dll/3rdparty/libtiff/tif_write.c
dll/3rdparty/libtiff/tif_zip.c
media/doc/3rd Party Files.txt
sdk/include/reactos/libs/libtiff/tif_dir.h
sdk/include/reactos/libs/libtiff/tiffio.h
sdk/include/reactos/libs/libtiff/tiffiop.h
sdk/include/reactos/libs/libtiff/tiffvers.h

index 54fc059..2cb9174 100644 (file)
@@ -40,7 +40,7 @@
 #include "tif_fax3.h"
 
 #ifndef HAVE_GETOPT
-extern int getopt(int, char**, char*);
+extern int getopt(int argc, char * const argv[], const char *optstring);
 #endif
 
 #define        streq(a,b)      (strcmp(a,b) == 0)
index f70f533..ef3f456 100644 (file)
 #include <precomp.h>
 #include "tif_predict.h"
 #include <math.h>
+#include <float.h>
 
 uint32
 _TIFFMultiply32(TIFF* tif, uint32 first, uint32 second, const char* where)
 {
-       uint32 bytes = first * second;
-
-       if (second && bytes / second != first) {
+       if (second && first > TIFF_UINT32_MAX / second) {
                TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where);
-               bytes = 0;
+               return 0;
        }
 
-       return bytes;
+       return first * second;
 }
 
 uint64
 _TIFFMultiply64(TIFF* tif, uint64 first, uint64 second, const char* where)
 {
-       uint64 bytes = first * second;
-
-       if (second && bytes / second != first) {
+       if (second && first > TIFF_UINT64_MAX / second) {
                TIFFErrorExt(tif->tif_clientdata, where, "Integer overflow in %s", where);
-               bytes = 0;
+               return 0;
        }
 
-       return bytes;
+       return first * second;
+}
+
+tmsize_t
+_TIFFMultiplySSize(TIFF* tif, tmsize_t first, tmsize_t second, const char* where)
+{
+    if( first <= 0 || second <= 0 )
+    {
+        if( tif != NULL && where != NULL )
+        {
+            TIFFErrorExt(tif->tif_clientdata, where,
+                        "Invalid argument to _TIFFMultiplySSize() in %s", where);
+        }
+        return 0;
+    }
+
+    if( first > TIFF_TMSIZE_T_MAX / second )
+    {
+        if( tif != NULL && where != NULL )
+        {
+            TIFFErrorExt(tif->tif_clientdata, where,
+                        "Integer overflow in %s", where);
+        }
+        return 0;
+    }
+    return first * second;
+}
+
+tmsize_t _TIFFCastUInt64ToSSize(TIFF* tif, uint64 val, const char* module)
+{
+    if( val > (uint64)TIFF_TMSIZE_T_MAX )
+    {
+        if( tif != NULL && module != NULL )
+        {
+            TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
+        }
+        return 0;
+    }
+    return (tmsize_t)val;
 }
 
 void*
@@ -63,13 +98,14 @@ _TIFFCheckRealloc(TIFF* tif, void* buffer,
                  tmsize_t nmemb, tmsize_t elem_size, const char* what)
 {
        void* cp = NULL;
-       tmsize_t bytes = nmemb * elem_size;
-
+        tmsize_t count = _TIFFMultiplySSize(tif, nmemb, elem_size, NULL);
        /*
-        * XXX: Check for integer overflow.
+        * Check for integer overflow.
         */
-       if (nmemb && elem_size && bytes / elem_size == nmemb)
-               cp = _TIFFrealloc(buffer, bytes);
+       if (count != 0)
+       {
+               cp = _TIFFrealloc(buffer, count);
+       }
 
        if (cp == NULL) {
                TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
@@ -358,6 +394,15 @@ _TIFFUInt64ToDouble(uint64 ui64)
        }
 }
 
+float _TIFFClampDoubleToFloat( double val )
+{
+    if( val > FLT_MAX )
+        return FLT_MAX;
+    if( val < -FLT_MAX )
+        return -FLT_MAX;
+    return (float)val;
+}
+
 int _TIFFSeekOK(TIFF* tif, toff_t off)
 {
     /* Huge offsets, especially -1 / UINT64_MAX, can cause issues */
index 66c4079..96d0002 100644 (file)
@@ -47,8 +47,8 @@ setByteArray(void** vpp, void* vp, size_t nmemb, size_t elem_size)
                *vpp = 0;
        }
        if (vp) {
-               tmsize_t bytes = (tmsize_t)(nmemb * elem_size);
-               if (elem_size && bytes / elem_size == nmemb)
+               tmsize_t bytes = _TIFFMultiplySSize(NULL, nmemb, elem_size, NULL);
+               if (bytes)
                        *vpp = (void*) _TIFFmalloc(bytes);
                if (*vpp)
                        _TIFFmemcpy(*vpp, vp, bytes);
@@ -88,13 +88,15 @@ setDoubleArrayOneValue(double** vpp, double value, size_t nmemb)
  * Install extra samples information.
  */
 static int
-setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v)
+setExtraSamples(TIFF* tif, va_list ap, uint32* v)
 {
 /* XXX: Unassociated alpha data == 999 is a known Corel Draw bug, see below */
 #define EXTRASAMPLE_COREL_UNASSALPHA 999 
 
        uint16* va;
        uint32 i;
+        TIFFDirectory* td = &tif->tif_dir;
+        static const char module[] = "setExtraSamples";
 
        *v = (uint16) va_arg(ap, uint16_vap);
        if ((uint16) *v > td->td_samplesperpixel)
@@ -116,6 +118,18 @@ setExtraSamples(TIFFDirectory* td, va_list ap, uint32* v)
                                return 0;
                }
        }
+
+        if ( td->td_transferfunction[0] != NULL && (td->td_samplesperpixel - *v > 1) &&
+                !(td->td_samplesperpixel - td->td_extrasamples > 1))
+        {
+                TIFFWarningExt(tif->tif_clientdata,module,
+                    "ExtraSamples tag value is changing, "
+                    "but TransferFunction was read with a different value. Cancelling it");
+                TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
+                _TIFFfree(td->td_transferfunction[0]);
+                td->td_transferfunction[0] = NULL;
+        }
+
        td->td_extrasamples = (uint16) *v;
        _TIFFsetShortArray(&td->td_sampleinfo, va, td->td_extrasamples);
        return 1;
@@ -153,15 +167,6 @@ bad:
        return (0);
 }
 
-static float TIFFClampDoubleToFloat( double val )
-{
-    if( val > FLT_MAX )
-        return FLT_MAX;
-    if( val < -FLT_MAX )
-        return -FLT_MAX;
-    return (float)val;
-}
-
 static int
 _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
 {
@@ -285,6 +290,18 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
                 _TIFFfree(td->td_smaxsamplevalue);
                 td->td_smaxsamplevalue = NULL;
             }
+            /* Test if 3 transfer functions instead of just one are now needed
+               See http://bugzilla.maptools.org/show_bug.cgi?id=2820 */
+            if( td->td_transferfunction[0] != NULL && (v - td->td_extrasamples > 1) &&
+                !(td->td_samplesperpixel - td->td_extrasamples > 1))
+            {
+                    TIFFWarningExt(tif->tif_clientdata,module,
+                        "SamplesPerPixel tag value is changing, "
+                        "but TransferFunction was read with a different value. Cancelling it");
+                    TIFFClrFieldBit(tif,FIELD_TRANSFERFUNCTION);
+                    _TIFFfree(td->td_transferfunction[0]);
+                    td->td_transferfunction[0] = NULL;
+            }
         }
                td->td_samplesperpixel = (uint16) v;
                break;
@@ -320,13 +337,13 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
         dblval = va_arg(ap, double);
         if( dblval < 0 )
             goto badvaluedouble;
-               td->td_xresolution = TIFFClampDoubleToFloat( dblval );
+               td->td_xresolution = _TIFFClampDoubleToFloat( dblval );
                break;
        case TIFFTAG_YRESOLUTION:
         dblval = va_arg(ap, double);
         if( dblval < 0 )
             goto badvaluedouble;
-               td->td_yresolution = TIFFClampDoubleToFloat( dblval );
+               td->td_yresolution = _TIFFClampDoubleToFloat( dblval );
                break;
        case TIFFTAG_PLANARCONFIG:
                v = (uint16) va_arg(ap, uint16_vap);
@@ -335,10 +352,10 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
                td->td_planarconfig = (uint16) v;
                break;
        case TIFFTAG_XPOSITION:
-               td->td_xposition = TIFFClampDoubleToFloat( va_arg(ap, double) );
+               td->td_xposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
                break;
        case TIFFTAG_YPOSITION:
-               td->td_yposition = TIFFClampDoubleToFloat( va_arg(ap, double) );
+               td->td_yposition = _TIFFClampDoubleToFloat( va_arg(ap, double) );
                break;
        case TIFFTAG_RESOLUTIONUNIT:
                v = (uint16) va_arg(ap, uint16_vap);
@@ -361,7 +378,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
                _TIFFsetShortArray(&td->td_colormap[2], va_arg(ap, uint16*), v32);
                break;
        case TIFFTAG_EXTRASAMPLES:
-               if (!setExtraSamples(td, ap, &v))
+               if (!setExtraSamples(tif, ap, &v))
                        goto badvalue;
                break;
        case TIFFTAG_MATTEING:
@@ -684,7 +701,7 @@ _TIFFVSetField(TIFF* tif, uint32 tag, va_list ap)
                                case TIFF_SRATIONAL:
                                case TIFF_FLOAT:
                                        {
-                                               float v2 = TIFFClampDoubleToFloat(va_arg(ap, double));
+                                               float v2 = _TIFFClampDoubleToFloat(va_arg(ap, double));
                                                _TIFFmemcpy(val, &v2, tv_size);
                                        }
                                        break;
@@ -1002,12 +1019,12 @@ _TIFFVGetField(TIFF* tif, uint32 tag, va_list ap)
                case TIFFTAG_STRIPOFFSETS:
                case TIFFTAG_TILEOFFSETS:
                        _TIFFFillStriles( tif );
-                       *va_arg(ap, uint64**) = td->td_stripoffset;
+                       *va_arg(ap, uint64**) = td->td_stripoffset_p;
                        break;
                case TIFFTAG_STRIPBYTECOUNTS:
                case TIFFTAG_TILEBYTECOUNTS:
                        _TIFFFillStriles( tif );
-                       *va_arg(ap, uint64**) = td->td_stripbytecount;
+                       *va_arg(ap, uint64**) = td->td_stripbytecount_p;
                        break;
                case TIFFTAG_MATTEING:
                        *va_arg(ap, uint16*) =
@@ -1266,8 +1283,9 @@ TIFFFreeDirectory(TIFF* tif)
        CleanupField(td_transferfunction[0]);
        CleanupField(td_transferfunction[1]);
        CleanupField(td_transferfunction[2]);
-       CleanupField(td_stripoffset);
-       CleanupField(td_stripbytecount);
+       CleanupField(td_stripoffset_p);
+       CleanupField(td_stripbytecount_p);
+        td->td_stripoffsetbyteallocsize = 0;
        TIFFClrFieldBit(tif, FIELD_YCBCRSUBSAMPLING);
        TIFFClrFieldBit(tif, FIELD_YCBCRPOSITIONING);
 
@@ -1280,10 +1298,8 @@ TIFFFreeDirectory(TIFF* tif)
        td->td_customValueCount = 0;
        CleanupField(td_customValues);
 
-#if defined(DEFER_STRILE_LOAD)
         _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
         _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
-#endif        
 }
 #undef CleanupField
 
@@ -1371,7 +1387,9 @@ TIFFDefaultDirectory(TIFF* tif)
        td->td_tilewidth = 0;
        td->td_tilelength = 0;
        td->td_tiledepth = 1;
+#ifdef STRIPBYTECOUNTSORTED_UNUSED
        td->td_stripbytecountsorted = 1; /* Our own arrays always sorted. */  
+#endif
        td->td_resolutionunit = RESUNIT_INCH;
        td->td_sampleformat = SAMPLEFORMAT_UINT;
        td->td_imagedepth = 1;
index ad33d62..432c5f8 100644 (file)
@@ -29,9 +29,6 @@
  */
 
 /* Suggested pending improvements:
- * - add a field 'ignore' to the TIFFDirEntry structure, to flag status,
- *   eliminating current use of the IGNORE value, and therefore eliminating
- *   current irrational behaviour on tags with tag id code 0
  * - add a field 'field_info' to the TIFFDirEntry structure, and set that with
  *   the pointer to the appropriate TIFFField structure early on in
  *   TIFFReadDirectory, so as to eliminate current possibly repetitive lookup.
 #include <float.h>
 #include <stdlib.h>
 
-#define IGNORE 0          /* tag placeholder used below */
 #define FAILED_FII    ((uint32) -1)
 
+/*
+ * Largest 64-bit signed integer value.
+ */
+#define TIFF_INT64_MAX ((int64)(TIFF_UINT64_MAX >> 1))
+
 #ifdef HAVE_IEEEFP
 # define TIFFCvtIEEEFloatToNative(tif, n, fp)
 # define TIFFCvtIEEEDoubleToNative(tif, n, dp)
@@ -164,6 +165,7 @@ static int TIFFFetchNormalTag(TIFF*, TIFFDirEntry*, int recover);
 static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uint64** lpp);
 static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*);
 static void ChopUpSingleUncompressedStrip(TIFF*);
+static void TryChopUpUncompressedBigTiff(TIFF*);
 static uint64 TIFFReadUInt64(const uint8 *value);
 static int _TIFFGetMaxColorChannels(uint16 photometric);
 
@@ -205,6 +207,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryByte(TIFF* tif, TIFFDirEntry* di
        switch (direntry->tdir_type)
        {
                case TIFF_BYTE:
+               case TIFF_UNDEFINED:    /* Support to read TIFF_UNDEFINED with field_readcount==1 */
                        TIFFReadDirEntryCheckedByte(tif,direntry,value);
                        return(TIFFReadDirEntryErrOk);
                case TIFF_SBYTE:
@@ -3287,11 +3290,6 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryCheckRangeLongSlong(int32 value)
                return(TIFFReadDirEntryErrOk);
 }
 
-/*
- * Largest 32-bit unsigned integer value.
- */
-#define TIFF_UINT32_MAX 0xFFFFFFFFU
-
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeLongLong8(uint64 value)
 {
@@ -3310,8 +3308,6 @@ TIFFReadDirEntryCheckRangeLongSlong8(int64 value)
                return(TIFFReadDirEntryErrOk);
 }
 
-#undef TIFF_UINT32_MAX
-
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeSlongLong(uint32 value)
 {
@@ -3377,11 +3373,6 @@ TIFFReadDirEntryCheckRangeLong8Slong8(int64 value)
                return(TIFFReadDirEntryErrOk);
 }
 
-/*
- * Largest 64-bit signed integer value.
- */
-#define TIFF_INT64_MAX ((int64)(((uint64) ~0) >> 1))
-
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value)
 {
@@ -3391,8 +3382,6 @@ TIFFReadDirEntryCheckRangeSlong8Long8(uint64 value)
                return(TIFFReadDirEntryErrOk);
 }
 
-#undef TIFF_INT64_MAX
-
 static enum TIFFReadDirEntryErr
 TIFFReadDirEntryData(TIFF* tif, uint64 offset, tmsize_t size, void* dest)
 {
@@ -3405,13 +3394,13 @@ TIFFReadDirEntryData(TIFF* tif, uint64 offset, tmsize_t size, void* dest)
        } else {
                size_t ma,mb;
                ma=(size_t)offset;
+                if( (uint64)ma!=offset ||
+                    ma > (~(size_t)0) - (size_t)size )
+                {
+                    return TIFFReadDirEntryErrIo;
+                }
                mb=ma+size;
-               if (((uint64)ma!=offset)
-                   || (mb < ma)
-                   || (mb - ma != (size_t) size)
-                   || (mb < (size_t)size)
-                   || (mb > (size_t)tif->tif_size)
-                   )
+               if (mb > (size_t)tif->tif_size)
                        return(TIFFReadDirEntryErrIo);
                _TIFFmemcpy(dest,tif->tif_base+ma,size);
        }
@@ -3534,6 +3523,49 @@ static int _TIFFGetMaxColorChannels( uint16 photometric )
     }
 }
 
+static int ByteCountLooksBad(TIFF* tif)
+{
+    /*
+        * Assume we have wrong StripByteCount value (in case
+        * of single strip) in following cases:
+        *   - it is equal to zero along with StripOffset;
+        *   - it is larger than file itself (in case of uncompressed
+        *     image);
+        *   - it is smaller than the size of the bytes per row
+        *     multiplied on the number of rows.  The last case should
+        *     not be checked in the case of writing new image,
+        *     because we may do not know the exact strip size
+        *     until the whole image will be written and directory
+        *     dumped out.
+        */
+    uint64 bytecount = TIFFGetStrileByteCount(tif, 0);
+    uint64 offset = TIFFGetStrileOffset(tif, 0);
+    uint64 filesize;
+
+    if( offset == 0 )
+        return 0;
+    if (bytecount == 0)
+        return 1;
+    if ( tif->tif_dir.td_compression != COMPRESSION_NONE )
+        return 0;
+    filesize = TIFFGetFileSize(tif);
+    if( offset <= filesize && bytecount > filesize - offset )
+        return 1;
+    if( tif->tif_mode == O_RDONLY )
+    {
+        uint64 scanlinesize = TIFFScanlineSize64(tif);
+        if( tif->tif_dir.td_imagelength > 0 &&
+            scanlinesize > TIFF_UINT64_MAX / tif->tif_dir.td_imagelength )
+        {
+            return 1;
+        }
+        if( bytecount < scanlinesize * tif->tif_dir.td_imagelength)
+            return 1;
+    }
+    return 0;
+}
+
+
 /*
  * Read the next TIFF directory from a file and convert it to the internal
  * format. We read directories sequentially.
@@ -3580,14 +3612,17 @@ TIFFReadDirectory(TIFF* tif)
                        uint16 nb;
                        for (na=ma+1, nb=mb+1; nb<dircount; na++, nb++)
                        {
-                               if (ma->tdir_tag==na->tdir_tag)
-                                       na->tdir_tag=IGNORE;
+                               if (ma->tdir_tag == na->tdir_tag) {
+                                       na->tdir_ignore = TRUE;
+                               }
                        }
                }
        }
         
        tif->tif_flags &= ~TIFF_BEENWRITING;    /* reset before new dir */
        tif->tif_flags &= ~TIFF_BUF4WRITE;      /* reset before new dir */
+       tif->tif_flags &= ~TIFF_CHOPPEDUPARRAYS;
+
        /* free any old stuff and reinit */
        TIFFFreeDirectory(tif);
        TIFFDefaultDirectory(tif);
@@ -3620,7 +3655,7 @@ TIFFReadDirectory(TIFF* tif)
        {
                if (!TIFFFetchNormalTag(tif,dp,0))
                        goto bad;
-               dp->tdir_tag=IGNORE;
+               dp->tdir_ignore = TRUE;
        }
        dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_COMPRESSION);
        if (dp)
@@ -3643,7 +3678,7 @@ TIFFReadDirectory(TIFF* tif)
                }
                if (!TIFFSetField(tif,TIFFTAG_COMPRESSION,value))
                        goto bad;
-               dp->tdir_tag=IGNORE;
+               dp->tdir_ignore = TRUE;
        }
        else
        {
@@ -3655,7 +3690,7 @@ TIFFReadDirectory(TIFF* tif)
         */
        for (di=0, dp=dir; di<dircount; di++, dp++)
        {
-               if (dp->tdir_tag!=IGNORE)
+               if (!dp->tdir_ignore)
                {
                        TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii);
                        if (fii == FAILED_FII)
@@ -3663,8 +3698,8 @@ TIFFReadDirectory(TIFF* tif)
                                TIFFWarningExt(tif->tif_clientdata, module,
                                    "Unknown field with tag %d (0x%x) encountered",
                                    dp->tdir_tag,dp->tdir_tag);
-                                /* the following knowingly leaks the 
-                                   anonymous field structure */
+                               /* the following knowingly leaks the 
+                                  anonymous field structure */
                                if (!_TIFFMergeFields(tif,
                                        _TIFFCreateAnonField(tif,
                                                dp->tdir_tag,
@@ -3675,18 +3710,18 @@ TIFFReadDirectory(TIFF* tif)
                                            "Registering anonymous field with tag %d (0x%x) failed",
                                            dp->tdir_tag,
                                            dp->tdir_tag);
-                                       dp->tdir_tag=IGNORE;
+                                       dp->tdir_ignore = TRUE;
                                } else {
                                        TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii);
                                        assert(fii != FAILED_FII);
                                }
                        }
                }
-               if (dp->tdir_tag!=IGNORE)
+               if (!dp->tdir_ignore)
                {
                        fip=tif->tif_fields[fii];
                        if (fip->field_bit==FIELD_IGNORE)
-                               dp->tdir_tag=IGNORE;
+                               dp->tdir_ignore = TRUE;
                        else
                        {
                                switch (dp->tdir_tag)
@@ -3708,12 +3743,12 @@ TIFFReadDirectory(TIFF* tif)
                                        case TIFFTAG_EXTRASAMPLES:
                                                if (!TIFFFetchNormalTag(tif,dp,0))
                                                        goto bad;
-                                               dp->tdir_tag=IGNORE;
+                                               dp->tdir_ignore = TRUE;
+                                               break;
+                                       default:
+                                               if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) )
+                                                       dp->tdir_ignore = TRUE;
                                                break;
-                                        default:
-                                            if( !_TIFFCheckFieldIsValidForCodec(tif, dp->tdir_tag) )
-                                                dp->tdir_tag=IGNORE;
-                                            break;
                                }
                        }
                }
@@ -3729,8 +3764,8 @@ TIFFReadDirectory(TIFF* tif)
        if ((tif->tif_dir.td_compression==COMPRESSION_OJPEG)&&
            (tif->tif_dir.td_planarconfig==PLANARCONFIG_SEPARATE))
        {
-        if (!_TIFFFillStriles(tif))
-            goto bad;
+               if (!_TIFFFillStriles(tif))
+                   goto bad;
                dp=TIFFReadDirectoryFindEntry(tif,dir,dircount,TIFFTAG_STRIPOFFSETS);
                if ((dp!=0)&&(dp->tdir_count==1))
                {
@@ -3802,190 +3837,200 @@ TIFFReadDirectory(TIFF* tif)
         */
        for (di=0, dp=dir; di<dircount; di++, dp++)
        {
-               switch (dp->tdir_tag)
-               {
-                       case IGNORE:
-                               break;
-                       case TIFFTAG_MINSAMPLEVALUE:
-                       case TIFFTAG_MAXSAMPLEVALUE:
-                       case TIFFTAG_BITSPERSAMPLE:
-                       case TIFFTAG_DATATYPE:
-                       case TIFFTAG_SAMPLEFORMAT:
-                               /*
-                                * The MinSampleValue, MaxSampleValue, BitsPerSample
-                                * DataType and SampleFormat tags are supposed to be
-                                * written as one value/sample, but some vendors
-                                * incorrectly write one value only -- so we accept
-                                * that as well (yuck). Other vendors write correct
-                                * value for NumberOfSamples, but incorrect one for
-                                * BitsPerSample and friends, and we will read this
-                                * too.
-                                */
-                               {
-                                       uint16 value;
-                                       enum TIFFReadDirEntryErr err;
-                                       err=TIFFReadDirEntryShort(tif,dp,&value);
-                                       if (err==TIFFReadDirEntryErrCount)
-                                               err=TIFFReadDirEntryPersampleShort(tif,dp,&value);
-                                       if (err!=TIFFReadDirEntryErrOk)
-                                       {
-                                               fip = TIFFFieldWithTag(tif,dp->tdir_tag);
-                                               TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
-                                               goto bad;
-                                       }
-                                       if (!TIFFSetField(tif,dp->tdir_tag,value))
-                                               goto bad;
-                    if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE )
-                        bitspersample_read = TRUE;
-                               }
-                               break;
-                       case TIFFTAG_SMINSAMPLEVALUE:
-                       case TIFFTAG_SMAXSAMPLEVALUE:
-                               {
-
-                                       double *data = NULL;
-                                       enum TIFFReadDirEntryErr err;
-                                       uint32 saved_flags;
-                                       int m;
-                                       if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel)
-                                               err = TIFFReadDirEntryErrCount;
-                                       else
-                                               err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
-                                       if (err!=TIFFReadDirEntryErrOk)
-                                       {
-                                               fip = TIFFFieldWithTag(tif,dp->tdir_tag);
-                                               TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
-                                               goto bad;
-                                       }
-                                       saved_flags = tif->tif_flags;
-                                       tif->tif_flags |= TIFF_PERSAMPLE;
-                                       m = TIFFSetField(tif,dp->tdir_tag,data);
-                                       tif->tif_flags = saved_flags;
-                                       _TIFFfree(data);
-                                       if (!m)
-                                               goto bad;
-                               }
-                               break;
-                       case TIFFTAG_STRIPOFFSETS:
-                       case TIFFTAG_TILEOFFSETS:
-#if defined(DEFER_STRILE_LOAD)
-                                _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry),
-                                             dp, sizeof(TIFFDirEntry) );
-#else                          
-                                if( tif->tif_dir.td_stripoffset != NULL )
-                                {
-                                    TIFFErrorExt(tif->tif_clientdata, module,
-                                        "tif->tif_dir.td_stripoffset is "
-                                        "already allocated. Likely duplicated "
-                                        "StripOffsets/TileOffsets tag");
-                                    goto bad;
-                                }
-                               if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripoffset))  
-                                       goto bad;
-#endif                                
-                               break;
-                       case TIFFTAG_STRIPBYTECOUNTS:
-                       case TIFFTAG_TILEBYTECOUNTS:
-#if defined(DEFER_STRILE_LOAD)
-                                _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry),
-                                             dp, sizeof(TIFFDirEntry) );
-#else                          
-                                if( tif->tif_dir.td_stripbytecount != NULL )
-                                {
-                                    TIFFErrorExt(tif->tif_clientdata, module,
-                                        "tif->tif_dir.td_stripbytecount is "
-                                        "already allocated. Likely duplicated "
-                                        "StripByteCounts/TileByteCounts tag");
-                                    goto bad;
-                                }
-                                if (!TIFFFetchStripThing(tif,dp,tif->tif_dir.td_nstrips,&tif->tif_dir.td_stripbytecount))  
-                                       goto bad;
-#endif                                
-                               break;
-                       case TIFFTAG_COLORMAP:
-                       case TIFFTAG_TRANSFERFUNCTION:
-                               {
-                                       enum TIFFReadDirEntryErr err;
-                                       uint32 countpersample;
-                                       uint32 countrequired;
-                                       uint32 incrementpersample;
-                                       uint16* value=NULL;
-                    /* It would be dangerous to instantiate those tag values */
-                    /* since if td_bitspersample has not yet been read (due to */
-                    /* unordered tags), it could be read afterwards with a */
-                    /* values greater than the default one (1), which may cause */
-                    /* crashes in user code */
-                    if( !bitspersample_read )
-                    {
-                        fip = TIFFFieldWithTag(tif,dp->tdir_tag);
-                        TIFFWarningExt(tif->tif_clientdata,module,
-                                       "Ignoring %s since BitsPerSample tag not found",
-                                       fip ? fip->field_name : "unknown tagname");
-                        continue;
-                    }
-                                       /* ColorMap or TransferFunction for high bit */
-                                       /* depths do not make much sense and could be */
-                                       /* used as a denial of service vector */
-                                       if (tif->tif_dir.td_bitspersample > 24)
-                                       {
-                                           fip = TIFFFieldWithTag(tif,dp->tdir_tag);
-                                           TIFFWarningExt(tif->tif_clientdata,module,
-                                               "Ignoring %s because BitsPerSample=%d>24",
-                                               fip ? fip->field_name : "unknown tagname",
-                                               tif->tif_dir.td_bitspersample);
-                                           continue;
-                                       }
-                                       countpersample=(1U<<tif->tif_dir.td_bitspersample);
-                                       if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample))
+               if (!dp->tdir_ignore) {
+                       switch (dp->tdir_tag) 
+                       {
+                               case TIFFTAG_MINSAMPLEVALUE:
+                               case TIFFTAG_MAXSAMPLEVALUE:
+                               case TIFFTAG_BITSPERSAMPLE:
+                               case TIFFTAG_DATATYPE:
+                               case TIFFTAG_SAMPLEFORMAT:
+                                       /*
+                                        * The MinSampleValue, MaxSampleValue, BitsPerSample
+                                        * DataType and SampleFormat tags are supposed to be
+                                        * written as one value/sample, but some vendors
+                                        * incorrectly write one value only -- so we accept
+                                        * that as well (yuck). Other vendors write correct
+                                        * value for NumberOfSamples, but incorrect one for
+                                        * BitsPerSample and friends, and we will read this
+                                        * too.
+                                        */
                                        {
-                                               countrequired=countpersample;
-                                               incrementpersample=0;
+                                               uint16 value;
+                                               enum TIFFReadDirEntryErr err;
+                                               err=TIFFReadDirEntryShort(tif,dp,&value);
+                                               if (err==TIFFReadDirEntryErrCount)
+                                                       err=TIFFReadDirEntryPersampleShort(tif,dp,&value);
+                                               if (err!=TIFFReadDirEntryErrOk)
+                                               {
+                                                       fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+                                                       TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
+                                                       goto bad;
+                                               }
+                                               if (!TIFFSetField(tif,dp->tdir_tag,value))
+                                                       goto bad;
+                                               if( dp->tdir_tag == TIFFTAG_BITSPERSAMPLE )
+                                                   bitspersample_read = TRUE;
                                        }
-                                       else
+                                       break;
+                               case TIFFTAG_SMINSAMPLEVALUE:
+                               case TIFFTAG_SMAXSAMPLEVALUE:
                                        {
-                                               countrequired=3*countpersample;
-                                               incrementpersample=countpersample;
+
+                                               double *data = NULL;
+                                               enum TIFFReadDirEntryErr err;
+                                               uint32 saved_flags;
+                                               int m;
+                                               if (dp->tdir_count != (uint64)tif->tif_dir.td_samplesperpixel)
+                                                       err = TIFFReadDirEntryErrCount;
+                                               else
+                                                       err = TIFFReadDirEntryDoubleArray(tif, dp, &data);
+                                               if (err!=TIFFReadDirEntryErrOk)
+                                               {
+                                                       fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+                                                       TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",0);
+                                                       goto bad;
+                                               }
+                                               saved_flags = tif->tif_flags;
+                                               tif->tif_flags |= TIFF_PERSAMPLE;
+                                               m = TIFFSetField(tif,dp->tdir_tag,data);
+                                               tif->tif_flags = saved_flags;
+                                               _TIFFfree(data);
+                                               if (!m)
+                                                       goto bad;
                                        }
-                                       if (dp->tdir_count!=(uint64)countrequired)
-                                               err=TIFFReadDirEntryErrCount;
-                                       else
-                                               err=TIFFReadDirEntryShortArray(tif,dp,&value);
-                                       if (err!=TIFFReadDirEntryErrOk)
-                    {
-                                               fip = TIFFFieldWithTag(tif,dp->tdir_tag);
-                                               TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1);
-                    }
-                                       else
+                                       break;
+                               case TIFFTAG_STRIPOFFSETS:
+                               case TIFFTAG_TILEOFFSETS:
+                                       _TIFFmemcpy( &(tif->tif_dir.td_stripoffset_entry),
+                                          dp, sizeof(TIFFDirEntry) );
+                                       break;
+                               case TIFFTAG_STRIPBYTECOUNTS:
+                               case TIFFTAG_TILEBYTECOUNTS:
+                                       _TIFFmemcpy( &(tif->tif_dir.td_stripbytecount_entry),
+                                          dp, sizeof(TIFFDirEntry) );
+                                       break;
+                               case TIFFTAG_COLORMAP:
+                               case TIFFTAG_TRANSFERFUNCTION:
                                        {
-                                               TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample);
-                                               _TIFFfree(value);
+                                               enum TIFFReadDirEntryErr err;
+                                               uint32 countpersample;
+                                               uint32 countrequired;
+                                               uint32 incrementpersample;
+                                               uint16* value=NULL;
+                                               /* It would be dangerous to instantiate those tag values */
+                                               /* since if td_bitspersample has not yet been read (due to */
+                                               /* unordered tags), it could be read afterwards with a */
+                                               /* values greater than the default one (1), which may cause */
+                                               /* crashes in user code */
+                                               if( !bitspersample_read )
+                                               {
+                                                       fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+                                                       TIFFWarningExt(tif->tif_clientdata,module,
+                                                               "Ignoring %s since BitsPerSample tag not found",
+                                                               fip ? fip->field_name : "unknown tagname");
+                                                       continue;
+                                               }
+                                               /* ColorMap or TransferFunction for high bit */
+                                               /* depths do not make much sense and could be */
+                                               /* used as a denial of service vector */
+                                               if (tif->tif_dir.td_bitspersample > 24)
+                                               {
+                                                       fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+                                                       TIFFWarningExt(tif->tif_clientdata,module,
+                                                               "Ignoring %s because BitsPerSample=%d>24",
+                                                               fip ? fip->field_name : "unknown tagname",
+                                                               tif->tif_dir.td_bitspersample);
+                                                       continue;
+                                               }
+                                               countpersample=(1U<<tif->tif_dir.td_bitspersample);
+                                               if ((dp->tdir_tag==TIFFTAG_TRANSFERFUNCTION)&&(dp->tdir_count==(uint64)countpersample))
+                                               {
+                                                       countrequired=countpersample;
+                                                       incrementpersample=0;
+                                               }
+                                               else
+                                               {
+                                                       countrequired=3*countpersample;
+                                                       incrementpersample=countpersample;
+                                               }
+                                               if (dp->tdir_count!=(uint64)countrequired)
+                                                       err=TIFFReadDirEntryErrCount;
+                                               else
+                                                       err=TIFFReadDirEntryShortArray(tif,dp,&value);
+                                               if (err!=TIFFReadDirEntryErrOk)
+                                               {
+                                                       fip = TIFFFieldWithTag(tif,dp->tdir_tag);
+                                                       TIFFReadDirEntryOutputErr(tif,err,module,fip ? fip->field_name : "unknown tagname",1);
+                                               }
+                                               else
+                                               {
+                                                       TIFFSetField(tif,dp->tdir_tag,value,value+incrementpersample,value+2*incrementpersample);
+                                                       _TIFFfree(value);
+                                               }
                                        }
-                               }
-                               break;
+                                       break;
 /* BEGIN REV 4.0 COMPATIBILITY */
-                       case TIFFTAG_OSUBFILETYPE:
-                               {
-                                       uint16 valueo;
-                                       uint32 value;
-                                       if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk)
+                               case TIFFTAG_OSUBFILETYPE:
                                        {
-                                               switch (valueo)
+                                               uint16 valueo;
+                                               uint32 value;
+                                               if (TIFFReadDirEntryShort(tif,dp,&valueo)==TIFFReadDirEntryErrOk)
                                                {
-                                                       case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break;
-                                                       case OFILETYPE_PAGE: value=FILETYPE_PAGE; break;
-                                                       default: value=0; break;
+                                                       switch (valueo)
+                                                       {
+                                                               case OFILETYPE_REDUCEDIMAGE: value=FILETYPE_REDUCEDIMAGE; break;
+                                                               case OFILETYPE_PAGE: value=FILETYPE_PAGE; break;
+                                                               default: value=0; break;
+                                                       }
+                                                       if (value!=0)
+                                                               TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value);
                                                }
-                                               if (value!=0)
-                                                       TIFFSetField(tif,TIFFTAG_SUBFILETYPE,value);
                                        }
-                               }
-                               break;
+                                       break;
 /* END REV 4.0 COMPATIBILITY */
-                       default:
-                               (void) TIFFFetchNormalTag(tif, dp, TRUE);
-                               break;
-               }
-       }
+                               default:
+                                       (void) TIFFFetchNormalTag(tif, dp, TRUE);
+                                       break;
+                               }
+                       } /* -- if (!dp->tdir_ignore) */
+               } /* -- for-loop -- */
+
+        if( tif->tif_mode == O_RDWR &&
+            tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
+            tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
+            tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
+            tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 )
+        {
+            /* Directory typically created with TIFFDeferStrileArrayWriting() */
+            TIFFSetupStrips(tif);
+        }
+        else if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) )
+        {
+            if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 )
+            {
+                if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripoffset_entry),
+                                         tif->tif_dir.td_nstrips,
+                                         &tif->tif_dir.td_stripoffset_p))
+                {
+                    goto bad;
+                }
+            }
+            if( tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 )
+            {
+                if (!TIFFFetchStripThing(tif,&(tif->tif_dir.td_stripbytecount_entry),
+                                         tif->tif_dir.td_nstrips,
+                                         &tif->tif_dir.td_stripbytecount_p))
+                {
+                    goto bad;
+                }
+            }
+        }
+
        /*
         * OJPEG hack:
         * - If a) compression is OJPEG, and b) photometric tag is missing,
@@ -4128,33 +4173,10 @@ TIFFReadDirectory(TIFF* tif)
                                "\"StripByteCounts\" field, calculating from imagelength");
                        if (EstimateStripByteCounts(tif, dir, dircount) < 0)
                            goto bad;
-               /*
-                * Assume we have wrong StripByteCount value (in case
-                * of single strip) in following cases:
-                *   - it is equal to zero along with StripOffset;
-                *   - it is larger than file itself (in case of uncompressed
-                *     image);
-                *   - it is smaller than the size of the bytes per row
-                *     multiplied on the number of rows.  The last case should
-                *     not be checked in the case of writing new image,
-                *     because we may do not know the exact strip size
-                *     until the whole image will be written and directory
-                *     dumped out.
-                */
-               #define BYTECOUNTLOOKSBAD \
-                   ( (tif->tif_dir.td_stripbytecount[0] == 0 && tif->tif_dir.td_stripoffset[0] != 0) || \
-                     (tif->tif_dir.td_compression == COMPRESSION_NONE && \
-                      (tif->tif_dir.td_stripoffset[0] <= TIFFGetFileSize(tif) && \
-                       tif->tif_dir.td_stripbytecount[0] > TIFFGetFileSize(tif) - tif->tif_dir.td_stripoffset[0])) || \
-                     (tif->tif_mode == O_RDONLY && \
-                      tif->tif_dir.td_compression == COMPRESSION_NONE && \
-                      tif->tif_dir.td_stripbytecount[0] < TIFFScanlineSize64(tif) * tif->tif_dir.td_imagelength) )
 
                } else if (tif->tif_dir.td_nstrips == 1
                            && !(tif->tif_flags&TIFF_ISTILED)
-                           && _TIFFFillStriles(tif)
-                          && tif->tif_dir.td_stripoffset[0] != 0
-                          && BYTECOUNTLOOKSBAD) {
+                          && ByteCountLooksBad(tif)) {
                        /*
                         * XXX: Plexus (and others) sometimes give a value of
                         * zero for a tag when they don't know what the
@@ -4166,13 +4188,13 @@ TIFFReadDirectory(TIFF* tif)
                        if(EstimateStripByteCounts(tif, dir, dircount) < 0)
                            goto bad;
 
-#if !defined(DEFER_STRILE_LOAD)
-               } else if (tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG
+               } else if (!(tif->tif_flags&TIFF_DEFERSTRILELOAD)
+                          && tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG
                           && tif->tif_dir.td_nstrips > 2
                           && tif->tif_dir.td_compression == COMPRESSION_NONE
-                          && tif->tif_dir.td_stripbytecount[0] != tif->tif_dir.td_stripbytecount[1]
-                          && tif->tif_dir.td_stripbytecount[0] != 0
-                          && tif->tif_dir.td_stripbytecount[1] != 0 ) {
+                          && TIFFGetStrileByteCount(tif, 0) != TIFFGetStrileByteCount(tif, 1)
+                          && TIFFGetStrileByteCount(tif, 0) != 0
+                          && TIFFGetStrileByteCount(tif, 1) != 0 ) {
                        /*
                         * XXX: Some vendors fill StripByteCount array with
                         * absolutely wrong values (it can be equal to
@@ -4187,7 +4209,6 @@ TIFFReadDirectory(TIFF* tif)
                            "Wrong \"StripByteCounts\" field, ignoring and calculating from imagelength");
                        if (EstimateStripByteCounts(tif, dir, dircount) < 0)
                            goto bad;
-#endif /* !defined(DEFER_STRILE_LOAD) */                        
                }
        }
        if (dir)
@@ -4202,26 +4223,27 @@ TIFFReadDirectory(TIFF* tif)
                else
                        tif->tif_dir.td_maxsamplevalue = (uint16)((1L<<tif->tif_dir.td_bitspersample)-1);
        }
+
+#ifdef STRIPBYTECOUNTSORTED_UNUSED
        /*
         * XXX: We can optimize checking for the strip bounds using the sorted
         * bytecounts array. See also comments for TIFFAppendToStrip()
         * function in tif_write.c.
         */
-#if !defined(DEFER_STRILE_LOAD)        
-       if (tif->tif_dir.td_nstrips > 1) {
+       if (!(tif->tif_flags&TIFF_DEFERSTRILELOAD) && tif->tif_dir.td_nstrips > 1) {
                uint32 strip;
 
                tif->tif_dir.td_stripbytecountsorted = 1;
                for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) {
-                       if (tif->tif_dir.td_stripoffset[strip - 1] >
-                           tif->tif_dir.td_stripoffset[strip]) {
+                       if (TIFFGetStrileOffset(tif, strip - 1) >
+                           TIFFGetStrileOffset(tif, strip)) {
                                tif->tif_dir.td_stripbytecountsorted = 0;
                                break;
                        }
                }
        }
-#endif /* !defined(DEFER_STRILE_LOAD) */
-        
+#endif
+
        /*
         * An opportunity for compression mode dependent tag fixup
         */
@@ -4240,11 +4262,20 @@ TIFFReadDirectory(TIFF* tif)
            (tif->tif_dir.td_nstrips==1)&&
            (tif->tif_dir.td_compression==COMPRESSION_NONE)&&  
            ((tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED))==TIFF_STRIPCHOP))
-    {
-        if ( !_TIFFFillStriles(tif) || !tif->tif_dir.td_stripbytecount )
-            return 0;
-               ChopUpSingleUncompressedStrip(tif);
-    }
+        {
+            ChopUpSingleUncompressedStrip(tif);
+        }
+
+        /* There are also uncompressed striped files with strips larger than */
+        /* 2 GB, which make them unfriendly with a lot of code. If possible, */
+        /* try to expose smaller "virtual" strips. */
+        if( tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG &&
+            tif->tif_dir.td_compression == COMPRESSION_NONE &&
+            (tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP &&
+            TIFFStripSize64(tif) > 0x7FFFFFFFUL )
+        {
+            TryChopUpUncompressedBigTiff(tif);
+        }
 
         /*
          * Clear the dirty directory flag. 
@@ -4396,17 +4427,17 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
                                TIFFWarningExt(tif->tif_clientdata, module,
                                    "Registering anonymous field with tag %d (0x%x) failed",
                                    dp->tdir_tag, dp->tdir_tag);
-                               dp->tdir_tag=IGNORE;
+                               dp->tdir_ignore = TRUE;
                        } else {
                                TIFFReadDirectoryFindFieldInfo(tif,dp->tdir_tag,&fii);
                                assert( fii != FAILED_FII );
                        }
                }
-               if (dp->tdir_tag!=IGNORE)
+               if (!dp->tdir_ignore)
                {
                        fip=tif->tif_fields[fii];
                        if (fip->field_bit==FIELD_IGNORE)
-                               dp->tdir_tag=IGNORE;
+                               dp->tdir_ignore = TRUE;
                        else
                        {
                                /* check data type */
@@ -4426,7 +4457,7 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
                                        TIFFWarningExt(tif->tif_clientdata, module,
                                            "Wrong data type %d for \"%s\"; tag ignored",
                                            dp->tdir_type,fip->field_name);
-                                       dp->tdir_tag=IGNORE;
+                                       dp->tdir_ignore = TRUE;
                                }
                                else
                                {
@@ -4440,21 +4471,21 @@ TIFFReadCustomDirectory(TIFF* tif, toff_t diroff,
                                                else
                                                        expected=(uint32)fip->field_readcount;
                                                if (!CheckDirCount(tif,dp,expected))
-                                                       dp->tdir_tag=IGNORE;
+                                                       dp->tdir_ignore = TRUE;
                                        }
                                }
                        }
-                       switch (dp->tdir_tag)
-                       {
-                               case IGNORE:
-                                       break;
-                               case EXIFTAG_SUBJECTDISTANCE:
-                                       (void) TIFFFetchSubjectDistance(tif,dp);
-                                       break;
-                               default:
-                                       (void) TIFFFetchNormalTag(tif, dp, TRUE);
-                                       break;
-                       }
+                       if (!dp->tdir_ignore) {
+                               switch (dp->tdir_tag) 
+                               {
+                                       case EXIFTAG_SUBJECTDISTANCE:
+                                               (void)TIFFFetchSubjectDistance(tif, dp);
+                                               break;
+                                       default:
+                                               (void)TIFFFetchNormalTag(tif, dp, TRUE);
+                                               break;
+                               }
+                       } /*-- if (!dp->tdir_ignore) */
                }
        }
        if (dir)
@@ -4487,12 +4518,12 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
         if( !_TIFFFillStrilesInternal( tif, 0 ) )
             return -1;
 
-       if (td->td_stripbytecount)
-               _TIFFfree(td->td_stripbytecount);
-       td->td_stripbytecount = (uint64*)
+       if (td->td_stripbytecount_p)
+               _TIFFfree(td->td_stripbytecount_p);
+       td->td_stripbytecount_p = (uint64*)
            _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
                "for \"StripByteCounts\" array");
-        if( td->td_stripbytecount == NULL )
+        if( td->td_stripbytecount_p == NULL )
             return -1;
 
        if (td->td_compression != COMPRESSION_NONE) {
@@ -4516,6 +4547,8 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
                                    dp->tdir_type);
                                return -1;
                        }
+                       if( dp->tdir_count > TIFF_UINT64_MAX / typewidth )
+                            return -1;
                        datasize=(uint64)typewidth*dp->tdir_count;
                        if (!(tif->tif_flags&TIFF_BIGTIFF))
                        {
@@ -4527,6 +4560,8 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
                                if (datasize<=8)
                                        datasize=0;
                        }
+                       if( space > TIFF_UINT64_MAX - datasize )
+                            return -1;
                        space+=datasize;
                }
                if( filesize < space )
@@ -4537,7 +4572,7 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
                if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
                        space /= td->td_samplesperpixel;
                for (strip = 0; strip < td->td_nstrips; strip++)
-                       td->td_stripbytecount[strip] = space;
+                       td->td_stripbytecount_p[strip] = space;
                /*
                 * This gross hack handles the case were the offset to
                 * the last strip is past the place where we think the strip
@@ -4546,18 +4581,30 @@ EstimateStripByteCounts(TIFF* tif, TIFFDirEntry* dir, uint16 dircount)
                 * of data in the strip and trim this number back accordingly.
                 */
                strip--;
-               if (td->td_stripoffset[strip]+td->td_stripbytecount[strip] > filesize)
-                       td->td_stripbytecount[strip] = filesize - td->td_stripoffset[strip];
+                if (td->td_stripoffset_p[strip] > TIFF_UINT64_MAX - td->td_stripbytecount_p[strip])
+                    return -1;
+               if (td->td_stripoffset_p[strip]+td->td_stripbytecount_p[strip] > filesize) {
+                    if( td->td_stripoffset_p[strip] >= filesize ) {
+                        /* Not sure what we should in that case... */
+                        td->td_stripbytecount_p[strip] = 0;
+                    } else {
+                        td->td_stripbytecount_p[strip] = filesize - td->td_stripoffset_p[strip];
+                    }
+                }
        } else if (isTiled(tif)) {
                uint64 bytespertile = TIFFTileSize64(tif);
 
                for (strip = 0; strip < td->td_nstrips; strip++)
-                   td->td_stripbytecount[strip] = bytespertile;
+                   td->td_stripbytecount_p[strip] = bytespertile;
        } else {
                uint64 rowbytes = TIFFScanlineSize64(tif);
                uint32 rowsperstrip = td->td_imagelength/td->td_stripsperimage;
                for (strip = 0; strip < td->td_nstrips; strip++)
-                       td->td_stripbytecount[strip] = rowbytes * rowsperstrip;
+                {
+                    if( rowbytes > 0 && rowsperstrip > TIFF_UINT64_MAX / rowbytes )
+                        return -1;
+                    td->td_stripbytecount_p[strip] = rowbytes * rowsperstrip;
+                }
        }
        TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
        if (!TIFFFieldSet(tif, FIELD_ROWSPERSTRIP))
@@ -4751,12 +4798,13 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir,
                }
        } else {
                tmsize_t m;
-               tmsize_t off = (tmsize_t) tif->tif_diroff;
-               if ((uint64)off!=tif->tif_diroff)
+               tmsize_t off;
+               if (tif->tif_diroff > (uint64)TIFF_INT64_MAX)
                {
                        TIFFErrorExt(tif->tif_clientdata,module,"Can not read TIFF directory count");
                        return(0);
                }
+               off = (tmsize_t) tif->tif_diroff;
 
                /*
                 * Check for integer overflow when validating the dir_off,
@@ -4874,6 +4922,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir,
        mb=dir;
        for (n=0; n<dircount16; n++)
        {
+               mb->tdir_ignore = FALSE;
                if (tif->tif_flags&TIFF_SWAB)
                        TIFFSwabShort((uint16*)ma);
                mb->tdir_tag=*(uint16*)ma;
@@ -4888,6 +4937,7 @@ TIFFFetchDirectory(TIFF* tif, uint64 diroff, TIFFDirEntry** pdir,
                                TIFFSwabLong((uint32*)ma);
                        mb->tdir_count=(uint64)(*(uint32*)ma);
                        ma+=sizeof(uint32);
+                       mb->tdir_offset.toff_long8=0;
                        *(uint32*)(&mb->tdir_offset)=*(uint32*)ma;
                        ma+=sizeof(uint32);
                }
@@ -5681,7 +5731,7 @@ TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir)
                        TIFFSwabArrayOfLong(m.i,2);
                if (m.i[0]==0)
                        n=0.0;
-               else if (m.i[0]==0xFFFFFFFF)
+               else if (m.i[0]==0xFFFFFFFF || m.i[1]==0)
                        /*
                         * XXX: Numerator 0xFFFFFFFF means that we have infinite
                         * distance. Indicate that with a negative floating point
@@ -5699,6 +5749,75 @@ TIFFFetchSubjectDistance(TIFF* tif, TIFFDirEntry* dir)
        }
 }
 
+static void allocChoppedUpStripArrays(TIFF* tif, uint32 nstrips,
+                                      uint64 stripbytes, uint32 rowsperstrip)
+{
+    TIFFDirectory *td = &tif->tif_dir;
+    uint64 bytecount;
+    uint64 offset;
+    uint64 last_offset;
+    uint64 last_bytecount;
+    uint32 i;
+    uint64 *newcounts;
+    uint64 *newoffsets;
+
+    offset = TIFFGetStrileOffset(tif, 0);
+    last_offset = TIFFGetStrileOffset(tif, td->td_nstrips-1);
+    last_bytecount = TIFFGetStrileByteCount(tif, td->td_nstrips-1);
+    if( last_offset > TIFF_UINT64_MAX - last_bytecount ||
+        last_offset + last_bytecount < offset )
+    {
+        return;
+    }
+    bytecount = last_offset + last_bytecount - offset;
+
+    newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
+                            "for chopped \"StripByteCounts\" array");
+    newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
+                            "for chopped \"StripOffsets\" array");
+    if (newcounts == NULL || newoffsets == NULL) {
+        /*
+        * Unable to allocate new strip information, give up and use
+        * the original one strip information.
+        */
+        if (newcounts != NULL)
+            _TIFFfree(newcounts);
+        if (newoffsets != NULL)
+            _TIFFfree(newoffsets);
+        return;
+    }
+
+    /*
+     * Fill the strip information arrays with new bytecounts and offsets
+     * that reflect the broken-up format.
+     */
+    for (i = 0; i < nstrips; i++)
+    {
+        if (stripbytes > bytecount)
+            stripbytes = bytecount;
+        newcounts[i] = stripbytes;
+        newoffsets[i] = stripbytes ? offset : 0;
+        offset += stripbytes;
+        bytecount -= stripbytes;
+    }
+
+    /*
+     * Replace old single strip info with multi-strip info.
+     */
+    td->td_stripsperimage = td->td_nstrips = nstrips;
+    TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
+
+    _TIFFfree(td->td_stripbytecount_p);
+    _TIFFfree(td->td_stripoffset_p);
+    td->td_stripbytecount_p = newcounts;
+    td->td_stripoffset_p = newoffsets;
+#ifdef STRIPBYTECOUNTSORTED_UNUSED
+    td->td_stripbytecountsorted = 1;
+#endif
+    tif->tif_flags |= TIFF_CHOPPEDUPARRAYS;
+}
+
+
 /*
  * Replace a single strip (tile) of uncompressed data by multiple strips
  * (tiles), each approximately STRIP_SIZE_DEFAULT bytes. This is useful for
@@ -5714,19 +5833,16 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
        uint32 rowblock;
        uint64 rowblockbytes;
        uint64 stripbytes;
-       uint32 strip;
        uint32 nstrips;
        uint32 rowsperstrip;
-       uint64* newcounts;
-       uint64* newoffsets;
 
-       bytecount = td->td_stripbytecount[0];
+       bytecount = TIFFGetStrileByteCount(tif, 0);
         /* On a newly created file, just re-opened to be filled, we */
         /* don't want strip chop to trigger as it is going to cause issues */
         /* later ( StripOffsets and StripByteCounts improperly filled) . */
         if( bytecount == 0 && tif->tif_mode != O_RDONLY )
             return;
-       offset = td->td_stripoffset[0];
+       offset = TIFFGetStrileByteCount(tif, 0);
        assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
        if ((td->td_photometric == PHOTOMETRIC_YCBCR)&&
            (!isUpSampled(tif)))
@@ -5769,98 +5885,503 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
             return;
         }
 
-       newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
-                               "for chopped \"StripByteCounts\" array");
-       newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
-                               "for chopped \"StripOffsets\" array");
-       if (newcounts == NULL || newoffsets == NULL) {
-               /*
-                * Unable to allocate new strip information, give up and use
-                * the original one strip information.
-                */
-               if (newcounts != NULL)
-                       _TIFFfree(newcounts);
-               if (newoffsets != NULL)
-                       _TIFFfree(newoffsets);
-               return;
-       }
-       /*
-        * Fill the strip information arrays with new bytecounts and offsets
-        * that reflect the broken-up format.
-        */
-       for (strip = 0; strip < nstrips; strip++) {
-               if (stripbytes > bytecount)
-                       stripbytes = bytecount;
-               newcounts[strip] = stripbytes;
-               newoffsets[strip] = stripbytes ? offset : 0;
-               offset += stripbytes;
-               bytecount -= stripbytes;
-       }
-       /*
-        * Replace old single strip info with multi-strip info.
-        */
-       td->td_stripsperimage = td->td_nstrips = nstrips;
-       TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsperstrip);
-
-       _TIFFfree(td->td_stripbytecount);
-       _TIFFfree(td->td_stripoffset);
-       td->td_stripbytecount = newcounts;
-       td->td_stripoffset = newoffsets;
-       td->td_stripbytecountsorted = 1;
+        allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip);
 }
 
-int _TIFFFillStriles( TIFF *tif )
+
+/*
+ * Replace a file with contiguous strips > 2 GB of uncompressed data by
+ * multiple smaller strips. This is useful for
+ * dealing with large images or for dealing with machines with a limited
+ * amount memory.
+ */
+static void TryChopUpUncompressedBigTiff( TIFF* tif )
 {
-    return _TIFFFillStrilesInternal( tif, 1 );
+    TIFFDirectory *td = &tif->tif_dir;
+    uint32 rowblock;
+    uint64 rowblockbytes;
+    uint32 i;
+    uint64 stripsize;
+    uint32 rowblocksperstrip;
+    uint32 rowsperstrip;
+    uint64 stripbytes;
+    uint32 nstrips;
+
+    stripsize = TIFFStripSize64(tif);
+
+    assert( tif->tif_dir.td_planarconfig == PLANARCONFIG_CONTIG );
+    assert( tif->tif_dir.td_compression == COMPRESSION_NONE );
+    assert( (tif->tif_flags&(TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP );
+    assert( stripsize > 0x7FFFFFFFUL );
+
+    /* On a newly created file, just re-opened to be filled, we */
+    /* don't want strip chop to trigger as it is going to cause issues */
+    /* later ( StripOffsets and StripByteCounts improperly filled) . */
+    if( TIFFGetStrileByteCount(tif, 0) == 0 && tif->tif_mode != O_RDONLY )
+        return;
+
+    if ((td->td_photometric == PHOTOMETRIC_YCBCR)&&
+        (!isUpSampled(tif)))
+        rowblock = td->td_ycbcrsubsampling[1];
+    else
+        rowblock = 1;
+    rowblockbytes = TIFFVStripSize64(tif, rowblock);
+    if( rowblockbytes == 0 || rowblockbytes > 0x7FFFFFFFUL )
+    {
+        /* In case of file with gigantic width */
+        return;
+    }
+
+    /* Check that the strips are contiguous and of the expected size */
+    for( i = 0; i < td->td_nstrips; i++ )
+    {
+        if( i == td->td_nstrips - 1 )
+        {
+            if( TIFFGetStrileByteCount(tif, i) < TIFFVStripSize64(
+                    tif, td->td_imagelength - i * td->td_rowsperstrip ) )
+            {
+                return;
+            }
+        }
+        else
+        {
+            if( TIFFGetStrileByteCount(tif, i) != stripsize )
+            {
+                return;
+            }
+            if( i > 0 && TIFFGetStrileOffset(tif, i) !=
+                    TIFFGetStrileOffset(tif, i-1) + TIFFGetStrileByteCount(tif, i-1) )
+            {
+                return;
+            }
+        }
+    }
+
+    /* Aim for 512 MB strips (that will still be manageable by 32 bit builds */
+    rowblocksperstrip = (uint32) (512 * 1024 * 1024 / rowblockbytes);
+    if( rowblocksperstrip == 0 )
+        rowblocksperstrip = 1;
+    rowsperstrip = rowblocksperstrip * rowblock;
+    stripbytes = rowblocksperstrip * rowblockbytes;
+    assert( stripbytes <= 0x7FFFFFFFUL );
+
+    nstrips = TIFFhowmany_32(td->td_imagelength, rowsperstrip);
+    if( nstrips == 0 )
+        return;
+
+    /* If we are going to allocate a lot of memory, make sure that the */
+    /* file is as big as needed */
+    if( tif->tif_mode == O_RDONLY &&
+        nstrips > 1000000 )
+    {
+        uint64 last_offset = TIFFGetStrileOffset(tif, td->td_nstrips-1);
+        uint64 filesize = TIFFGetFileSize(tif);
+        uint64 last_bytecount = TIFFGetStrileByteCount(tif, td->td_nstrips-1);
+        if( last_offset > filesize ||
+            last_bytecount > filesize - last_offset )
+        {
+            return;
+        }
+    }
+
+    allocChoppedUpStripArrays(tif, nstrips, stripbytes, rowsperstrip);
 }
 
-static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount )
+
+TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+static uint64 _TIFFUnsanitizedAddUInt64AndInt(uint64 a, int b)
 {
-#if defined(DEFER_STRILE_LOAD)
-        register TIFFDirectory *td = &tif->tif_dir;
-        int return_value = 1;
+    return a + b;
+}
 
-        if( td->td_stripoffset != NULL )
-                return 1;
+/* Read the value of [Strip|Tile]Offset or [Strip|Tile]ByteCount around
+ * strip/tile of number strile. Also fetch the neighbouring values using a
+ * 4096 byte page size.
+ */
+static
+int _TIFFPartialReadStripArray( TIFF* tif, TIFFDirEntry* dirent,
+                                int strile, uint64* panVals )
+{
+    static const char module[] = "_TIFFPartialReadStripArray";
+#define IO_CACHE_PAGE_SIZE 4096
+
+    size_t sizeofval;
+    const int bSwab = (tif->tif_flags & TIFF_SWAB) != 0;
+    int sizeofvalint;
+    uint64 nBaseOffset;
+    uint64 nOffset;
+    uint64 nOffsetStartPage;
+    uint64 nOffsetEndPage;
+    tmsize_t nToRead;
+    tmsize_t nRead;
+    uint64 nLastStripOffset;
+    int iStartBefore;
+    int i;
+    const uint32 arraySize = tif->tif_dir.td_stripoffsetbyteallocsize;
+    unsigned char buffer[2 * IO_CACHE_PAGE_SIZE];
+
+    assert( dirent->tdir_count > 4 );
+
+    if( dirent->tdir_type == TIFF_SHORT )
+    {
+        sizeofval = sizeof(uint16);
+    }
+    else if( dirent->tdir_type == TIFF_LONG )
+    {
+        sizeofval = sizeof(uint32);
+    }
+    else if( dirent->tdir_type == TIFF_LONG8 )
+    {
+        sizeofval = sizeof(uint64);
+    }
+    else
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                 "Invalid type for [Strip|Tile][Offset/ByteCount] tag");
+        panVals[strile] = 0;
+        return 0;
+    }
+    sizeofvalint = (int)(sizeofval);
 
-        if( td->td_stripoffset_entry.tdir_count == 0 )
+    if( tif->tif_flags&TIFF_BIGTIFF )
+    {
+        uint64 offset = dirent->tdir_offset.toff_long8;
+        if( bSwab )
+            TIFFSwabLong8(&offset);
+        nBaseOffset = offset;
+    }
+    else
+    {
+        uint32 offset = dirent->tdir_offset.toff_long;
+        if( bSwab )
+            TIFFSwabLong(&offset);
+        nBaseOffset = offset;
+    }
+    /* To avoid later unsigned integer overflows */
+    if( nBaseOffset > (uint64)TIFF_INT64_MAX )
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                 "Cannot read offset/size for strile %d", strile);
+        panVals[strile] = 0;
+        return 0;
+    }
+    nOffset = nBaseOffset + sizeofval * strile;
+    nOffsetStartPage =
+        (nOffset / IO_CACHE_PAGE_SIZE) * IO_CACHE_PAGE_SIZE;
+    nOffsetEndPage = nOffsetStartPage + IO_CACHE_PAGE_SIZE;
+
+    if( nOffset + sizeofval > nOffsetEndPage )
+        nOffsetEndPage += IO_CACHE_PAGE_SIZE;
+#undef IO_CACHE_PAGE_SIZE
+
+    nLastStripOffset = nBaseOffset + arraySize * sizeofval;
+    if( nLastStripOffset < nOffsetEndPage )
+        nOffsetEndPage = nLastStripOffset;
+    if( nOffsetStartPage >= nOffsetEndPage )
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                 "Cannot read offset/size for strile %d", strile);
+        panVals[strile] = 0;
+        return 0;
+    }
+    if (!SeekOK(tif,nOffsetStartPage))
+    {
+        panVals[strile] = 0;
+        return 0;
+    }
+
+    nToRead = (tmsize_t)(nOffsetEndPage - nOffsetStartPage);
+    nRead = TIFFReadFile(tif, buffer, nToRead);
+    if( nRead < nToRead )
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                 "Cannot read offset/size for strile around ~%d", strile);
+        return 0;
+    }
+    iStartBefore = -(int)((nOffset - nOffsetStartPage) / sizeofval);
+    if( strile + iStartBefore < 0 )
+        iStartBefore = -strile;
+    for( i = iStartBefore;
+         (uint32)(strile + i) < arraySize &&
+         _TIFFUnsanitizedAddUInt64AndInt(nOffset, (i + 1) * sizeofvalint) <= nOffsetEndPage;
+         ++i )
+    {
+        if( sizeofval == sizeof(uint16) )
+        {
+            uint16 val;
+            memcpy(&val,
+                   buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
+                   sizeof(val));
+            if( bSwab )
+                TIFFSwabShort(&val);
+            panVals[strile + i] = val;
+        }
+        else if( sizeofval == sizeof(uint32) )
+        {
+            uint32 val;
+            memcpy(&val,
+                   buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
+                   sizeof(val));
+            if( bSwab )
+                TIFFSwabLong(&val);
+            panVals[strile + i] = val;
+        }
+        else
+        {
+            uint64 val;
+            memcpy(&val,
+                   buffer + (nOffset - nOffsetStartPage) + i * sizeofvalint,
+                   sizeof(val));
+            if( bSwab )
+                TIFFSwabLong8(&val);
+            panVals[strile + i] = val;
+        }
+    }
+    return 1;
+}
+
+static int _TIFFFetchStrileValue(TIFF* tif,
+                                 uint32 strile,
+                                 TIFFDirEntry* dirent,
+                                 uint64** parray)
+{
+    static const char module[] = "_TIFFFetchStrileValue";
+    TIFFDirectory *td = &tif->tif_dir;
+    if( strile >= dirent->tdir_count )
+    {
+        return 0;
+    }
+    if( strile >= td->td_stripoffsetbyteallocsize )
+    {
+        uint32 nStripArrayAllocBefore = td->td_stripoffsetbyteallocsize;
+        uint32 nStripArrayAllocNew;
+        uint64 nArraySize64;
+        size_t nArraySize;
+        uint64* offsetArray;
+        uint64* bytecountArray;
+
+        if( strile > 1000000 )
+        {
+            uint64 filesize = TIFFGetFileSize(tif);
+            /* Avoid excessive memory allocation attempt */
+            /* For such a big blockid we need at least a TIFF_LONG per strile */
+            /* for the offset array. */
+            if( strile > filesize / sizeof(uint32) )
+            {
+                TIFFErrorExt(tif->tif_clientdata, module, "File too short");
                 return 0;
+            }
+        }
 
-        if (!TIFFFetchStripThing(tif,&(td->td_stripoffset_entry),
-                                 td->td_nstrips,&td->td_stripoffset))
+        if( td->td_stripoffsetbyteallocsize == 0 &&
+            td->td_nstrips < 1024 * 1024 )
         {
-                return_value = 0;
+            nStripArrayAllocNew = td->td_nstrips;
+        }
+        else
+        {
+#define TIFF_MAX(a,b) (((a)>(b)) ? (a) : (b))
+#define TIFF_MIN(a,b) (((a)<(b)) ? (a) : (b))
+            nStripArrayAllocNew = TIFF_MAX(strile + 1, 1024U * 512U );
+            if( nStripArrayAllocNew < 0xFFFFFFFFU / 2  )
+                nStripArrayAllocNew *= 2;
+            nStripArrayAllocNew = TIFF_MIN(nStripArrayAllocNew, td->td_nstrips);
+        }
+        assert( strile < nStripArrayAllocNew );
+        nArraySize64 = (uint64)sizeof(uint64) * nStripArrayAllocNew;
+        nArraySize = (size_t)(nArraySize64);
+#if SIZEOF_SIZE_T == 4
+        if( nArraySize != nArraySize64 )
+        {
+            TIFFErrorExt(tif->tif_clientdata, module,
+                        "Cannot allocate strip offset and bytecount arrays");
+            return 0;
         }
+#endif
+        offsetArray = (uint64*)(
+            _TIFFrealloc( td->td_stripoffset_p, nArraySize ) );
+        bytecountArray = (uint64*)(
+            _TIFFrealloc( td->td_stripbytecount_p, nArraySize ) );
+        if( offsetArray )
+            td->td_stripoffset_p = offsetArray;
+        if( bytecountArray )
+            td->td_stripbytecount_p = bytecountArray;
+        if( offsetArray && bytecountArray )
+        {
+            td->td_stripoffsetbyteallocsize = nStripArrayAllocNew;
+            /* Initialize new entries to ~0 / -1 */
+            memset(td->td_stripoffset_p + nStripArrayAllocBefore,
+                0xFF,
+                (td->td_stripoffsetbyteallocsize - nStripArrayAllocBefore) * sizeof(uint64) );
+            memset(td->td_stripbytecount_p + nStripArrayAllocBefore,
+                0xFF,
+                (td->td_stripoffsetbyteallocsize - nStripArrayAllocBefore) * sizeof(uint64) );
+        }
+        else
+        {
+            TIFFErrorExt(tif->tif_clientdata, module,
+                        "Cannot allocate strip offset and bytecount arrays");
+            _TIFFfree(td->td_stripoffset_p);
+            td->td_stripoffset_p = NULL;
+            _TIFFfree(td->td_stripbytecount_p);
+            td->td_stripbytecount_p = NULL;
+            td->td_stripoffsetbyteallocsize = 0;
+        }
+    }
+    if( *parray == NULL || strile >= td->td_stripoffsetbyteallocsize )
+        return 0;
 
-        if (loadStripByteCount &&
-            !TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry),
-                                 td->td_nstrips,&td->td_stripbytecount))
+    if( ~((*parray)[strile]) == 0 )
+    {
+        if( !_TIFFPartialReadStripArray( tif, dirent, strile, *parray ) )
         {
-                return_value = 0;
+            (*parray)[strile] = 0;
+            return 0;
         }
+    }
 
-        _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
-        _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
+    return 1;
+}
 
-       if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) {
-               uint32 strip;
+static uint64 _TIFFGetStrileOffsetOrByteCountValue(TIFF *tif, uint32 strile,
+                                                   TIFFDirEntry* dirent,
+                                                   uint64** parray,
+                                                   int *pbErr)
+{
+    TIFFDirectory *td = &tif->tif_dir;
+    if( pbErr )
+        *pbErr = 0;
+    if( (tif->tif_flags&TIFF_DEFERSTRILELOAD) && !(tif->tif_flags&TIFF_CHOPPEDUPARRAYS) )
+    {
+        if( !(tif->tif_flags&TIFF_LAZYSTRILELOAD) ||
+            /* If the values may fit in the toff_long/toff_long8 member */
+            /* then use _TIFFFillStriles to simplify _TIFFFetchStrileValue */
+            dirent->tdir_count <= 4 )
+        {
+            if( !_TIFFFillStriles(tif) )
+            {
+                if( pbErr )
+                    *pbErr = 1;
+                /* Do not return, as we want this function to always */
+                /* return the same value if called several times with */
+                /* the same arguments */
+            }
+        }
+        else
+        {
+             if( !_TIFFFetchStrileValue(tif, strile, dirent, parray) )
+             {
+                if( pbErr )
+                    *pbErr = 1;
+                 return 0;
+             }
+        }
+    }
+    if( *parray == NULL || strile >= td->td_nstrips )
+    {
+        if( pbErr )
+            *pbErr = 1;
+        return 0;
+    }
+    return (*parray)[strile];
+}
 
-               tif->tif_dir.td_stripbytecountsorted = 1;
-               for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) {
-                       if (tif->tif_dir.td_stripoffset[strip - 1] >
-                           tif->tif_dir.td_stripoffset[strip]) {
-                               tif->tif_dir.td_stripbytecountsorted = 0;
-                               break;
-                       }
-               }
-       }
+/* Return the value of the TileOffsets/StripOffsets array for the specified tile/strile */
+uint64 TIFFGetStrileOffset(TIFF *tif, uint32 strile)
+{
+    return TIFFGetStrileOffsetWithErr(tif, strile, NULL);
+}
+
+/* Return the value of the TileOffsets/StripOffsets array for the specified tile/strile */
+uint64 TIFFGetStrileOffsetWithErr(TIFF *tif, uint32 strile, int *pbErr)
+{
+    TIFFDirectory *td = &tif->tif_dir;
+    return _TIFFGetStrileOffsetOrByteCountValue(tif, strile,
+                               &(td->td_stripoffset_entry),
+                               &(td->td_stripoffset_p), pbErr);
+}
+
+/* Return the value of the TileByteCounts/StripByteCounts array for the specified tile/strile */
+uint64 TIFFGetStrileByteCount(TIFF *tif, uint32 strile)
+{
+    return TIFFGetStrileByteCountWithErr(tif, strile, NULL);
+}
+
+/* Return the value of the TileByteCounts/StripByteCounts array for the specified tile/strile */
+uint64 TIFFGetStrileByteCountWithErr(TIFF *tif, uint32 strile, int *pbErr)
+{
+    TIFFDirectory *td = &tif->tif_dir;
+    return _TIFFGetStrileOffsetOrByteCountValue(tif, strile,
+                               &(td->td_stripbytecount_entry),
+                               &(td->td_stripbytecount_p), pbErr);
+}
 
-        return return_value;
-#else /* !defined(DEFER_STRILE_LOAD) */
-        (void) tif;
-        (void) loadStripByteCount;
+
+int _TIFFFillStriles( TIFF *tif )
+{
+    return _TIFFFillStrilesInternal( tif, 1 );
+}
+
+static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount )
+{
+    register TIFFDirectory *td = &tif->tif_dir;
+    int return_value = 1;
+
+    /* Do not do anything if TIFF_DEFERSTRILELOAD is not set */
+    if( !(tif->tif_flags&TIFF_DEFERSTRILELOAD) || (tif->tif_flags&TIFF_CHOPPEDUPARRAYS) != 0 )
         return 1;
-#endif 
+
+    if( tif->tif_flags&TIFF_LAZYSTRILELOAD )
+    {
+        /* In case of lazy loading, reload completely the arrays */
+        _TIFFfree(td->td_stripoffset_p);
+        _TIFFfree(td->td_stripbytecount_p);
+        td->td_stripoffset_p = NULL;
+        td->td_stripbytecount_p = NULL;
+        td->td_stripoffsetbyteallocsize = 0;
+        tif->tif_flags &= ~TIFF_LAZYSTRILELOAD;
+    }
+
+    /* If stripoffset array is already loaded, exit with success */
+    if( td->td_stripoffset_p != NULL )
+            return 1;
+
+    /* If tdir_count was cancelled, then we already got there, but in error */
+    if( td->td_stripoffset_entry.tdir_count == 0 )
+            return 0;
+
+    if (!TIFFFetchStripThing(tif,&(td->td_stripoffset_entry),
+                                td->td_nstrips,&td->td_stripoffset_p))
+    {
+            return_value = 0;
+    }
+
+    if (loadStripByteCount &&
+        !TIFFFetchStripThing(tif,&(td->td_stripbytecount_entry),
+                                td->td_nstrips,&td->td_stripbytecount_p))
+    {
+            return_value = 0;
+    }
+
+    _TIFFmemset( &(td->td_stripoffset_entry), 0, sizeof(TIFFDirEntry));
+    _TIFFmemset( &(td->td_stripbytecount_entry), 0, sizeof(TIFFDirEntry));
+
+#ifdef STRIPBYTECOUNTSORTED_UNUSED
+    if (tif->tif_dir.td_nstrips > 1 && return_value == 1 ) {
+            uint32 strip;
+
+            tif->tif_dir.td_stripbytecountsorted = 1;
+            for (strip = 1; strip < tif->tif_dir.td_nstrips; strip++) {
+                    if (tif->tif_dir.td_stripoffset_p[strip - 1] >
+                        tif->tif_dir.td_stripoffset_p[strip]) {
+                            tif->tif_dir.td_stripbytecountsorted = 0;
+                            break;
+                    }
+            }
+    }
+#endif
+
+    return return_value;
 }
 
 
index acc41c8..f9a38f6 100644 (file)
@@ -182,6 +182,51 @@ TIFFWriteDirectory(TIFF* tif)
        return TIFFWriteDirectorySec(tif,TRUE,TRUE,NULL);
 }
 
+/*
+ * This is an advanced writing function that must be used in a particular
+ * sequence, and generally together with TIFFForceStrileArrayWriting(),
+ * to make its intended effect. Its aim is to modify the location
+ * where the [Strip/Tile][Offsets/ByteCounts] arrays are located in the file.
+ * More precisely, when TIFFWriteCheck() will be called, the tag entries for
+ * those arrays will be written with type = count = offset = 0 as a temporary
+ * value.
+ *
+ * Its effect is only valid for the current directory, and before
+ * TIFFWriteDirectory() is first called, and  will be reset when
+ * changing directory.
+ *
+ * The typical sequence of calls is:
+ * TIFFOpen()
+ * [ TIFFCreateDirectory(tif) ]
+ * Set fields with calls to TIFFSetField(tif, ...)
+ * TIFFDeferStrileArrayWriting(tif)
+ * TIFFWriteCheck(tif, ...)
+ * TIFFWriteDirectory(tif)
+ * ... potentially create other directories and come back to the above directory
+ * TIFFForceStrileArrayWriting(tif): emit the arrays at the end of file
+ *
+ * Returns 1 in case of success, 0 otherwise.
+ */
+int TIFFDeferStrileArrayWriting(TIFF* tif)
+{
+    static const char module[] = "TIFFDeferStrileArrayWriting";
+    if (tif->tif_mode == O_RDONLY)
+    {
+        TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+                     "File opened in read-only mode");
+        return 0;
+    }
+    if( tif->tif_diroff != 0 )
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                     "Directory has already been written");
+        return 0;
+    }
+
+    tif->tif_dir.td_deferstrilearraywriting = TRUE;
+    return 1;
+}
+
 /*
  * Similar to TIFFWriteDirectory(), writes the directory out
  * but leaves all data structures in memory so that it can be
@@ -193,7 +238,7 @@ TIFFCheckpointDirectory(TIFF* tif)
 {
        int rc;
        /* Setup the strips arrays, if they haven't already been. */
-       if (tif->tif_dir.td_stripoffset == NULL)
+       if (tif->tif_dir.td_stripoffset_p == NULL)
            (void) TIFFSetupStrips(tif);
        rc = TIFFWriteDirectorySec(tif,TRUE,FALSE,NULL);
        (void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
@@ -528,12 +573,12 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
                        {
                                if (!isTiled(tif))
                                {
-                                       if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount))
+                                       if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount_p))
                                                goto bad;
                                }
                                else
                                {
-                                       if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount))
+                                       if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEBYTECOUNTS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripbytecount_p))
                                                goto bad;
                                }
                        }
@@ -541,7 +586,7 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
                        {
                                if (!isTiled(tif))
                                {
-                    /* td_stripoffset might be NULL in an odd OJPEG case. See
+                    /* td_stripoffset_p might be NULL in an odd OJPEG case. See
                      *  tif_dirread.c around line 3634.
                      * XXX: OJPEG hack.
                      * If a) compression is OJPEG, b) it's not a tiled TIFF,
@@ -552,13 +597,13 @@ TIFFWriteDirectorySec(TIFF* tif, int isimage, int imagedone, uint64* pdiroff)
                      * We can get here when using tiffset on such a file.
                      * See http://bugzilla.maptools.org/show_bug.cgi?id=2500
                     */
-                    if (tif->tif_dir.td_stripoffset != NULL &&
-                        !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset))
+                    if (tif->tif_dir.td_stripoffset_p != NULL &&
+                        !TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_STRIPOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p))
                         goto bad;
                                }
                                else
                                {
-                                       if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset))
+                                       if (!TIFFWriteDirectoryTagLongLong8Array(tif,&ndir,dir,TIFFTAG_TILEOFFSETS,tif->tif_dir.td_nstrips,tif->tif_dir.td_stripoffset_p))
                                                goto bad;
                                }
                        }
@@ -946,15 +991,6 @@ bad:
        return(0);
 }
 
-static float TIFFClampDoubleToFloat( double val )
-{
-    if( val > FLT_MAX )
-        return FLT_MAX;
-    if( val < -FLT_MAX )
-        return -FLT_MAX;
-    return (float)val;
-}
-
 static int8 TIFFClampDoubleToInt8( double val )
 {
     if( val > 127 )
@@ -1029,7 +1065,7 @@ TIFFWriteDirectoryTagSampleformatArray(TIFF* tif, uint32* ndir, TIFFDirEntry* di
                        if (tif->tif_dir.td_bitspersample<=32)
                        {
                                for (i = 0; i < count; ++i)
-                                       ((float*)conv)[i] = TIFFClampDoubleToFloat(value[i]);
+                                       ((float*)conv)[i] = _TIFFClampDoubleToFloat(value[i]);
                                ok = TIFFWriteDirectoryTagFloatArray(tif,ndir,dir,tag,count,(float*)conv);
                        }
                        else
@@ -1661,22 +1697,52 @@ TIFFWriteDirectoryTagShortLong(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint1
                return(TIFFWriteDirectoryTagCheckedLong(tif,ndir,dir,tag,value));
 }
 
+static int _WriteAsType(TIFF* tif, uint64 strile_size, uint64 uncompressed_threshold)
+{
+    const uint16 compression = tif->tif_dir.td_compression;
+    if ( compression == COMPRESSION_NONE )
+    {
+        return strile_size > uncompressed_threshold;
+    }
+    else if ( compression == COMPRESSION_JPEG ||
+              compression == COMPRESSION_LZW ||
+              compression == COMPRESSION_ADOBE_DEFLATE ||
+              compression == COMPRESSION_LZMA ||
+              compression == COMPRESSION_LERC ||
+              compression == COMPRESSION_ZSTD ||
+              compression == COMPRESSION_WEBP )
+    {
+        /* For a few select compression types, we assume that in the worst */
+        /* case the compressed size will be 10 times the uncompressed size */
+        /* This is overly pessismistic ! */
+        return strile_size >= uncompressed_threshold / 10;
+    }
+    return 1;
+}
+
+static int WriteAsLong8(TIFF* tif, uint64 strile_size)
+{
+    return _WriteAsType(tif, strile_size, 0xFFFFFFFFU);
+}
+
+static int WriteAsLong4(TIFF* tif, uint64 strile_size)
+{
+    return _WriteAsType(tif, strile_size, 0xFFFFU);
+}
+
 /************************************************************************/
 /*                TIFFWriteDirectoryTagLongLong8Array()                 */
 /*                                                                      */
-/*      Write out LONG8 array as LONG8 for BigTIFF or LONG for          */
-/*      Classic TIFF with some checking.                                */
+/*      Write out LONG8 array and write a SHORT/LONG/LONG8 depending    */
+/*      on strile size and Classic/BigTIFF mode.                        */
 /************************************************************************/
 
 static int
 TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag, uint32 count, uint64* value)
 {
     static const char module[] = "TIFFWriteDirectoryTagLongLong8Array";
-    uint64* ma;
-    uint32 mb;
-    uint32* p;
-    uint32* q;
     int o;
+    int write_aslong4;
 
     /* is this just a counting pass? */
     if (dir==NULL)
@@ -1685,37 +1751,105 @@ TIFFWriteDirectoryTagLongLong8Array(TIFF* tif, uint32* ndir, TIFFDirEntry* dir,
         return(1);
     }
 
-    /* We always write LONG8 for BigTIFF, no checking needed. */
-    if( tif->tif_flags&TIFF_BIGTIFF )
-        return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,
-                                                      tag,count,value);
-
-    /*
-    ** For classic tiff we want to verify everything is in range for LONG
-    ** and convert to long format.
-    */
+    if( tif->tif_dir.td_deferstrilearraywriting )
+    {
+        return TIFFWriteDirectoryTagData(tif, ndir, dir, tag, TIFF_NOTYPE, 0, 0, NULL);
+    }
 
-    p = _TIFFmalloc(count*sizeof(uint32));
-    if (p==NULL)
+    if( tif->tif_flags&TIFF_BIGTIFF )
     {
-        TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
-        return(0);
+        int write_aslong8 = 1;
+        /* In the case of ByteCounts array, we may be able to write them on */
+        /* LONG if the strip/tilesize is not too big. */
+        /* Also do that for count > 1 in the case someone would want to create */
+        /* a single-strip file with a growing height, in which case using */
+        /* LONG8 will be safer. */
+        if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
+        {
+            write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
+        }
+        else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
+        {
+            write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
+        }
+        if( write_aslong8 )
+        {
+            return TIFFWriteDirectoryTagCheckedLong8Array(tif,ndir,dir,
+                                                        tag,count,value);
+        }
     }
 
-    for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
+    write_aslong4 = 1;
+    if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
     {
-        if (*ma>0xFFFFFFFF)
+        write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
+    }
+    else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
+    {
+        write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
+    }
+    if( write_aslong4 )
+    {
+        /*
+        ** For classic tiff we want to verify everything is in range for LONG
+        ** and convert to long format.
+        */
+
+        uint32* p = _TIFFmalloc(count*sizeof(uint32));
+        uint32* q;
+        uint64* ma;
+        uint32 mb;
+
+        if (p==NULL)
         {
-            TIFFErrorExt(tif->tif_clientdata,module,
-                         "Attempt to write value larger than 0xFFFFFFFF in Classic TIFF file.");
-            _TIFFfree(p);
+            TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
             return(0);
         }
-        *q= (uint32)(*ma);
+
+        for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
+        {
+            if (*ma>0xFFFFFFFF)
+            {
+                TIFFErrorExt(tif->tif_clientdata,module,
+                            "Attempt to write value larger than 0xFFFFFFFF in LONG array.");
+                _TIFFfree(p);
+                return(0);
+            }
+            *q= (uint32)(*ma);
+        }
+
+        o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p);
+        _TIFFfree(p);
     }
+    else
+    {
+        uint16* p = _TIFFmalloc(count*sizeof(uint16));
+        uint16* q;
+        uint64* ma;
+        uint32 mb;
 
-    o=TIFFWriteDirectoryTagCheckedLongArray(tif,ndir,dir,tag,count,p);
-    _TIFFfree(p);
+        if (p==NULL)
+        {
+            TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
+            return(0);
+        }
+
+        for (q=p, ma=value, mb=0; mb<count; ma++, mb++, q++)
+        {
+            if (*ma>0xFFFF)
+            {
+                /* Should not happen normally given the check we did before */
+                TIFFErrorExt(tif->tif_clientdata,module,
+                            "Attempt to write value larger than 0xFFFF in SHORT array.");
+                _TIFFfree(p);
+                return(0);
+            }
+            *q= (uint16)(*ma);
+        }
+
+        o=TIFFWriteDirectoryTagCheckedShortArray(tif,ndir,dir,tag,count,p);
+        _TIFFfree(p);
+    }
 
     return(o);
 }
@@ -1893,12 +2027,14 @@ TIFFWriteDirectoryTagTransferfunction(TIFF* tif, uint32* ndir, TIFFDirEntry* dir
                n=3;
        if (n==3)
        {
-               if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)))
+               if (tif->tif_dir.td_transferfunction[2] == NULL ||
+                   !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[2],m*sizeof(uint16)))
                        n=2;
        }
        if (n==2)
        {
-               if (!_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)))
+               if (tif->tif_dir.td_transferfunction[1] == NULL ||
+                   !_TIFFmemcmp(tif->tif_dir.td_transferfunction[0],tif->tif_dir.td_transferfunction[1],m*sizeof(uint16)))
                        n=1;
        }
        if (n==0)
@@ -2428,7 +2564,12 @@ TIFFWriteDirectoryTagData(TIFF* tif, uint32* ndir, TIFFDirEntry* dir, uint16 tag
        dir[m].tdir_count=count;
        dir[m].tdir_offset.toff_long8 = 0;
        if (datalength<=((tif->tif_flags&TIFF_BIGTIFF)?0x8U:0x4U))
-               _TIFFmemcpy(&dir[m].tdir_offset,data,datalength);
+        {
+            if( data && datalength )
+            {
+                _TIFFmemcpy(&dir[m].tdir_offset,data,datalength);
+            }
+        }
        else
        {
                uint64 na,nb;
@@ -2820,13 +2961,60 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
             TIFFSwabLong8( &entry_offset );
     }
 
+/* -------------------------------------------------------------------- */
+/*      When a dummy tag was written due to TIFFDeferStrileArrayWriting() */
+/* -------------------------------------------------------------------- */
+    if( entry_offset == 0 && entry_count == 0 && entry_type == 0 )
+    {
+        if( tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS )
+        {
+            entry_type = (tif->tif_flags&TIFF_BIGTIFF) ? TIFF_LONG8 : TIFF_LONG; 
+        }
+        else
+        {
+            int write_aslong8 = 1;
+            if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
+            {
+                write_aslong8 = WriteAsLong8(tif, TIFFStripSize64(tif));
+            }
+            else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
+            {
+                write_aslong8 = WriteAsLong8(tif, TIFFTileSize64(tif));
+            }
+            if( write_aslong8 )
+            {
+                entry_type = TIFF_LONG8;
+            }
+            else
+            {
+                int write_aslong4 = 1;
+                if( count > 1 && tag == TIFFTAG_STRIPBYTECOUNTS )
+                {
+                    write_aslong4 = WriteAsLong4(tif, TIFFStripSize64(tif));
+                }
+                else if( count > 1 && tag == TIFFTAG_TILEBYTECOUNTS )
+                {
+                    write_aslong4 = WriteAsLong4(tif, TIFFTileSize64(tif));
+                }
+                if( write_aslong4 )
+                {
+                    entry_type = TIFF_LONG;
+                }
+                else
+                {
+                    entry_type = TIFF_SHORT;
+                }
+            }
+        }
+    }
+
 /* -------------------------------------------------------------------- */
 /*      What data type do we want to write this as?                     */
 /* -------------------------------------------------------------------- */
     if( TIFFDataWidth(in_datatype) == 8 && !(tif->tif_flags&TIFF_BIGTIFF) )
     {
         if( in_datatype == TIFF_LONG8 )
-            datatype = TIFF_LONG;
+            datatype = entry_type == TIFF_SHORT ? TIFF_SHORT : TIFF_LONG;
         else if( in_datatype == TIFF_SLONG8 )
             datatype = TIFF_SLONG;
         else if( in_datatype == TIFF_IFD8 )
@@ -2834,8 +3022,21 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
         else
             datatype = in_datatype;
     }
-    else 
-        datatype = in_datatype;
+    else
+    {
+        if( in_datatype == TIFF_LONG8 &&
+            (entry_type == TIFF_SHORT || entry_type == TIFF_LONG ||
+             entry_type == TIFF_LONG8 ) )
+            datatype = entry_type;
+        else if( in_datatype == TIFF_SLONG8 &&
+            (entry_type == TIFF_SLONG || entry_type == TIFF_SLONG8 ) )
+            datatype = entry_type;
+        else if( in_datatype == TIFF_IFD8 &&
+            (entry_type == TIFF_IFD || entry_type == TIFF_IFD8 ) )
+            datatype = entry_type;
+        else
+            datatype = in_datatype;
+    }
 
 /* -------------------------------------------------------------------- */
 /*      Prepare buffer of actual data to write.  This includes          */
@@ -2884,6 +3085,29 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
             }
         }
     }
+    else if( datatype == TIFF_SHORT && in_datatype == TIFF_LONG8 )
+    {
+       tmsize_t i;
+
+        for( i = 0; i < count; i++ )
+        {
+            ((uint16 *) buf_to_write)[i] =
+                (uint16) ((uint64 *) data)[i];
+            if( (uint64) ((uint16 *) buf_to_write)[i] != ((uint64 *) data)[i] )
+            {
+                _TIFFfree( buf_to_write );
+                TIFFErrorExt( tif->tif_clientdata, module,
+                              "Value exceeds 16bit range of output type." );
+                return 0;
+            }
+        }
+    }
+    else
+    {
+        TIFFErrorExt( tif->tif_clientdata, module,
+                      "Unhandled type conversion." );
+        return 0;
+    }
 
     if( TIFFDataWidth(datatype) > 1 && (tif->tif_flags&TIFF_SWAB) )
     {
@@ -2915,6 +3139,23 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
         }
     }
 
+    if( (tag == TIFFTAG_TILEOFFSETS || tag == TIFFTAG_STRIPOFFSETS) &&
+        tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
+        tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
+        tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 )
+    {
+        tif->tif_dir.td_stripoffset_entry.tdir_type = datatype;
+        tif->tif_dir.td_stripoffset_entry.tdir_count = count;
+    }
+    else if( (tag == TIFFTAG_TILEBYTECOUNTS || tag == TIFFTAG_STRIPBYTECOUNTS) &&
+        tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
+        tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
+        tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 )
+    {
+        tif->tif_dir.td_stripbytecount_entry.tdir_type = datatype;
+        tif->tif_dir.td_stripbytecount_entry.tdir_count = count;
+    }
+
 /* -------------------------------------------------------------------- */
 /*      If the tag type, and count match, then we just write it out     */
 /*      over the old values without altering the directory entry at     */
@@ -2966,6 +3207,7 @@ _TIFFRewriteField(TIFF* tif, uint16 tag, TIFFDataType in_datatype,
 /*      Adjust the directory entry.                                     */
 /* -------------------------------------------------------------------- */
     entry_type = datatype;
+    entry_count = (uint64)count;
     memcpy( direntry_raw + 2, &entry_type, sizeof(uint16) );
     if (tif->tif_flags&TIFF_SWAB)
         TIFFSwabShort( (uint16 *) (direntry_raw + 2) );
index d76738a..773def1 100644 (file)
@@ -46,36 +46,8 @@ TIFFFlush(TIFF* tif)
         && !(tif->tif_flags & TIFF_DIRTYDIRECT) 
         && tif->tif_mode == O_RDWR )
     {
-        uint64  *offsets=NULL, *sizes=NULL;
-
-        if( TIFFIsTiled(tif) )
-        {
-            if( TIFFGetField( tif, TIFFTAG_TILEOFFSETS, &offsets ) 
-                && TIFFGetField( tif, TIFFTAG_TILEBYTECOUNTS, &sizes ) 
-                && _TIFFRewriteField( tif, TIFFTAG_TILEOFFSETS, TIFF_LONG8, 
-                                      tif->tif_dir.td_nstrips, offsets )
-                && _TIFFRewriteField( tif, TIFFTAG_TILEBYTECOUNTS, TIFF_LONG8, 
-                                      tif->tif_dir.td_nstrips, sizes ) )
-            {
-                tif->tif_flags &= ~TIFF_DIRTYSTRIP;
-                tif->tif_flags &= ~TIFF_BEENWRITING;
-                return 1;
-            }
-        }
-        else
-        {
-            if( TIFFGetField( tif, TIFFTAG_STRIPOFFSETS, &offsets ) 
-                && TIFFGetField( tif, TIFFTAG_STRIPBYTECOUNTS, &sizes ) 
-                && _TIFFRewriteField( tif, TIFFTAG_STRIPOFFSETS, TIFF_LONG8, 
-                                      tif->tif_dir.td_nstrips, offsets )
-                && _TIFFRewriteField( tif, TIFFTAG_STRIPBYTECOUNTS, TIFF_LONG8, 
-                                      tif->tif_dir.td_nstrips, sizes ) )
-            {
-                tif->tif_flags &= ~TIFF_DIRTYSTRIP;
-                tif->tif_flags &= ~TIFF_BEENWRITING;
-                return 1;
-            }
-        }
+        if( TIFFForceStrileArrayWriting(tif) )
+            return 1;
     }
 
     if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) 
@@ -85,6 +57,92 @@ TIFFFlush(TIFF* tif)
     return (1);
 }
 
+/*
+ * This is an advanced writing function that must be used in a particular
+ * sequence, and together with TIFFDeferStrileArrayWriting(),
+ * to make its intended effect. Its aim is to force the writing of
+ * the [Strip/Tile][Offsets/ByteCounts] arrays at the end of the file, when
+ * they have not yet been rewritten.
+ *
+ * The typical sequence of calls is:
+ * TIFFOpen()
+ * [ TIFFCreateDirectory(tif) ]
+ * Set fields with calls to TIFFSetField(tif, ...)
+ * TIFFDeferStrileArrayWriting(tif)
+ * TIFFWriteCheck(tif, ...)
+ * TIFFWriteDirectory(tif)
+ * ... potentially create other directories and come back to the above directory
+ * TIFFForceStrileArrayWriting(tif)
+ *
+ * Returns 1 in case of success, 0 otherwise.
+ */
+int TIFFForceStrileArrayWriting(TIFF* tif)
+{
+    static const char module[] = "TIFFForceStrileArrayWriting";
+    const int isTiled = TIFFIsTiled(tif);
+
+    if (tif->tif_mode == O_RDONLY)
+    {
+        TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
+                     "File opened in read-only mode");
+        return 0;
+    }
+    if( tif->tif_diroff == 0 )
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                     "Directory has not yet been written");
+        return 0;
+    }
+    if( (tif->tif_flags & TIFF_DIRTYDIRECT) != 0 )
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                     "Directory has changes other than the strile arrays. "
+                     "TIFFRewriteDirectory() should be called instead");
+        return 0;
+    }
+
+    if( !(tif->tif_flags & TIFF_DIRTYSTRIP) )
+    {
+        if( !(tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
+             tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
+             tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
+             tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
+             tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
+             tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
+             tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
+             tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0) )
+        {
+            TIFFErrorExt(tif->tif_clientdata, module,
+                        "Function not called together with "
+                        "TIFFDeferStrileArrayWriting()");
+            return 0;
+        }
+
+        if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif))
+            return 0;
+    }
+
+    if( _TIFFRewriteField( tif,
+                           isTiled ? TIFFTAG_TILEOFFSETS :
+                                     TIFFTAG_STRIPOFFSETS,
+                           TIFF_LONG8,
+                           tif->tif_dir.td_nstrips,
+                           tif->tif_dir.td_stripoffset_p )
+        && _TIFFRewriteField( tif,
+                              isTiled ? TIFFTAG_TILEBYTECOUNTS :
+                                        TIFFTAG_STRIPBYTECOUNTS,
+                              TIFF_LONG8,
+                              tif->tif_dir.td_nstrips,
+                              tif->tif_dir.td_stripbytecount_p ) )
+    {
+        tif->tif_flags &= ~TIFF_DIRTYSTRIP;
+        tif->tif_flags &= ~TIFF_BEENWRITING;
+        return 1;
+    }
+
+    return 0;
+}
+
 /*
  * Flush buffered data to the file.
  *
index 7fc00d6..c2f5d29 100644 (file)
@@ -755,9 +755,8 @@ gtTileSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
        uint32 leftmost_tw;
 
        tilesize = TIFFTileSize(tif);  
-       bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,tilesize);
+       bufsize = _TIFFMultiplySSize(tif, alpha?4:3,tilesize, "gtTileSeparate");
        if (bufsize == 0) {
-               TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtTileSeparate");
                return (0);
        }
 
@@ -950,16 +949,23 @@ gtStripContig(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
        fromskew = (w < imagewidth ? imagewidth - w : 0);
        for (row = 0; row < h; row += nrow)
        {
+               uint32 temp;
                rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
                nrow = (row + rowstoread > h ? h - row : rowstoread);
                nrowsub = nrow;
                if ((nrowsub%subsamplingver)!=0)
                        nrowsub+=subsamplingver-nrowsub%subsamplingver;
+               temp = (row + img->row_offset)%rowsperstrip + nrowsub;
+               if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
+               {
+                       TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripContig");
+                       return 0;
+               }
                if (_TIFFReadEncodedStripAndAllocBuffer(tif,
                    TIFFComputeStrip(tif,row+img->row_offset, 0),
                    (void**)(&buf),
                     maxstripsize,
-                   ((row + img->row_offset)%rowsperstrip + nrowsub) * scanline)==(tmsize_t)(-1)
+                   temp * scanline)==(tmsize_t)(-1)
                    && (buf == NULL || img->stoponerr))
                {
                        ret = 0;
@@ -1019,9 +1025,8 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
         uint16 colorchannels;
 
        stripsize = TIFFStripSize(tif);  
-       bufsize = TIFFSafeMultiply(tmsize_t,alpha?4:3,stripsize);
+       bufsize = _TIFFMultiplySSize(tif,alpha?4:3,stripsize, "gtStripSeparate");
        if (bufsize == 0) {
-               TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in %s", "gtStripSeparate");
                return (0);
        }
 
@@ -1053,15 +1058,22 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
        fromskew = (w < imagewidth ? imagewidth - w : 0);
        for (row = 0; row < h; row += nrow)
        {
+                uint32 temp;
                rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
                nrow = (row + rowstoread > h ? h - row : rowstoread);
                offset_row = row + img->row_offset;
+                temp = (row + img->row_offset)%rowsperstrip + nrow;
+                if( scanline > 0 && temp > (size_t)(TIFF_TMSIZE_T_MAX / scanline) )
+                {
+                        TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "Integer overflow in gtStripSeparate");
+                        return 0;
+                }
                 if( buf == NULL )
                 {
                     if (_TIFFReadEncodedStripAndAllocBuffer(
                             tif, TIFFComputeStrip(tif, offset_row, 0),
                             (void**) &buf, bufsize,
-                            ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1)
+                            temp * scanline)==(tmsize_t)(-1)
                         && (buf == NULL || img->stoponerr))
                     {
                             ret = 0;
@@ -1081,7 +1093,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                     }
                 }
                else if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 0),
-                   p0, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1)
+                   p0, temp * scanline)==(tmsize_t)(-1)
                    && img->stoponerr)
                {
                        ret = 0;
@@ -1089,7 +1101,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                }
                if (colorchannels > 1 
                     && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 1),
-                                            p1, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1)
+                                            p1, temp * scanline) == (tmsize_t)(-1)
                    && img->stoponerr)
                {
                        ret = 0;
@@ -1097,7 +1109,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                }
                if (colorchannels > 1 
                     && TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, 2),
-                                            p2, ((row + img->row_offset)%rowsperstrip + nrow) * scanline) == (tmsize_t)(-1)
+                                            p2, temp * scanline) == (tmsize_t)(-1)
                    && img->stoponerr)
                {
                        ret = 0;
@@ -1106,7 +1118,7 @@ gtStripSeparate(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
                if (alpha)
                {
                        if (TIFFReadEncodedStrip(tif, TIFFComputeStrip(tif, offset_row, colorchannels),
-                           pa, ((row + img->row_offset)%rowsperstrip + nrow) * scanline)==(tmsize_t)(-1)
+                           pa, temp * scanline)==(tmsize_t)(-1)
                            && img->stoponerr)
                        {
                                ret = 0;
@@ -2957,7 +2969,7 @@ TIFFReadRGBATileExt(TIFF* tif, uint32 col, uint32 row, uint32 * raster, int stop
     if( !TIFFIsTiled( tif ) )
     {
                TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif),
-                                 "Can't use TIFFReadRGBATile() with stripped file.");
+                                 "Can't use TIFFReadRGBATile() with striped file.");
                return (0);
     }
     
index f2ddc33..93ae2ea 100644 (file)
@@ -780,12 +780,9 @@ JPEGFixupTagsSubsampling(TIFF* tif)
         */
        static const char module[] = "JPEGFixupTagsSubsampling";
        struct JPEGFixupTagsSubsamplingData m;
+        uint64 fileoffset = TIFFGetStrileOffset(tif, 0);
 
-        _TIFFFillStriles( tif );
-        
-        if( tif->tif_dir.td_stripbytecount == NULL
-            || tif->tif_dir.td_stripoffset == NULL
-            || tif->tif_dir.td_stripbytecount[0] == 0 )
+        if( fileoffset == 0 )
         {
             /* Do not even try to check if the first strip/tile does not
                yet exist, as occurs when GDAL has created a new NULL file
@@ -804,9 +801,9 @@ JPEGFixupTagsSubsampling(TIFF* tif)
        }
        m.buffercurrentbyte=NULL;
        m.bufferbytesleft=0;
-       m.fileoffset=tif->tif_dir.td_stripoffset[0];
+       m.fileoffset=fileoffset;
        m.filepositioned=0;
-       m.filebytesleft=tif->tif_dir.td_stripbytecount[0];
+       m.filebytesleft=TIFFGetStrileByteCount(tif, 0);
        if (!JPEGFixupTagsSubsamplingSec(&m))
                TIFFWarningExt(tif->tif_clientdata,module,
                    "Unable to auto-correct subsampling values, likely corrupt JPEG compressed data in first strip/tile; auto-correcting skipped");
@@ -1566,7 +1563,7 @@ JPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
                                        JSAMPLE *outptr = (JSAMPLE*)tmpbuf + clumpoffset;
 #else
                                        JSAMPLE *outptr = (JSAMPLE*)buf + clumpoffset;
-                                       if (cc < (tmsize_t) (clumpoffset + samples_per_clump*(clumps_per_line-1) + hsamp)) {
+                                       if (cc < (tmsize_t)(clumpoffset + (tmsize_t)samples_per_clump*(clumps_per_line-1) + hsamp)) {
                                                TIFFErrorExt(tif->tif_clientdata, "JPEGDecodeRaw",
                                                             "application buffer not large enough for all data, possible subsampling issue");
                                                return 0;
@@ -2126,8 +2123,8 @@ JPEGEncodeRaw(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
        /* data is expected to be supplied in multiples of a clumpline */
        /* a clumpline is equivalent to v_sampling desubsampled scanlines */
        /* TODO: the following calculation of bytesperclumpline, should substitute calculation of sp->bytesperline, except that it is per v_sampling lines */
-       bytesperclumpline = (((sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling)
-                            *(sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7)
+       bytesperclumpline = ((((tmsize_t)sp->cinfo.c.image_width+sp->h_sampling-1)/sp->h_sampling)
+                            *((tmsize_t)sp->h_sampling*sp->v_sampling+2)*sp->cinfo.c.data_precision+7)
                            /8;
 
        nrows = ( cc / bytesperclumpline ) * sp->v_sampling;
index 3b9e633..dfebd18 100644 (file)
@@ -742,9 +742,14 @@ LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 #undef exp2  /* Conflict with C'99 function */
 #define exp2(x)                exp(M_LN2*(x))
 
-#define itrunc(x,m)    ((m)==SGILOGENCODE_NODITHER ? \
-                               (int)(x) : \
-                               (int)((x) + rand()*(1./RAND_MAX) - .5))
+static int itrunc(double x, int m)
+{
+    if( m == SGILOGENCODE_NODITHER )
+        return (int)x;
+    /* Silence CoverityScan warning about bad crypto function */
+    /* coverity[dont_call] */
+    return (int)(x + rand()*(1./RAND_MAX) - .5);
+}
 
 #if !LOGLUV_PUBLIC
 static
@@ -1264,16 +1269,10 @@ LogL16GuessDataFmt(TIFFDirectory *td)
        return (SGILOGDATAFMT_UNKNOWN);
 }
 
-
-#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)
 {
-        if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 )
-            return 0;
-        return m1 * m2;
+        return _TIFFMultiplySSize(NULL, m1, m2, NULL);
 }
 
 static int
@@ -1507,7 +1506,7 @@ LogLuvSetupEncode(TIFF* tif)
        switch (td->td_photometric) {
        case PHOTOMETRIC_LOGLUV:
                if (!LogLuvInitState(tif))
-                       break;
+                       return (0);
                if (td->td_compression == COMPRESSION_SGILOG24) {
                        tif->tif_encoderow = LogLuvEncode24;
                        switch (sp->user_datafmt) {
@@ -1540,7 +1539,7 @@ LogLuvSetupEncode(TIFF* tif)
                break;
        case PHOTOMETRIC_LOGL:
                if (!LogL16InitState(tif))
-                       break;
+                       return (0);
                tif->tif_encoderow = LogL16Encode;  
                switch (sp->user_datafmt) {
                case SGILOGDATAFMT_FLOAT:
@@ -1556,7 +1555,7 @@ LogLuvSetupEncode(TIFF* tif)
                TIFFErrorExt(tif->tif_clientdata, module,
                    "Inappropriate photometric interpretation %d for SGILog compression; %s",
                    td->td_photometric, "must be either LogLUV or LogL");
-               break;
+               return (0);
        }
        sp->encoder_state = 1;
        return (1);
index 4726053..9c06935 100644 (file)
@@ -247,6 +247,8 @@ LZWSetupDecode(TIFF* tif)
                /*
                 * Zero-out the unused entries
                  */
+                /* Silence false positive */
+                /* coverity[overrun-buffer-arg] */
                  _TIFFmemset(&sp->dec_codetab[CODE_CLEAR], 0,
                             (CODE_FIRST - CODE_CLEAR) * sizeof (code_t));
        }
index 27385d8..bf0d1a2 100644 (file)
@@ -243,6 +243,7 @@ typedef enum {
 typedef struct {
        TIFF* tif;
         int decoder_ok;
+        int error_in_raw_data_decoding;
        #ifndef LIBJPEG_ENCAP_EXTERNAL
        JMP_BUF exit_jmpbuf;
        #endif
@@ -678,7 +679,7 @@ OJPEGPreDecode(TIFF* tif, uint16 s)
                if (OJPEGReadSecondarySos(tif,s)==0)
                        return(0);
        }
-       if isTiled(tif)
+       if (isTiled(tif))
                m=tif->tif_curtile;
        else
                m=tif->tif_curstrip;
@@ -742,6 +743,7 @@ OJPEGPreDecodeSkipRaw(TIFF* tif)
                }
                m-=sp->subsampling_convert_clines-sp->subsampling_convert_state;
                sp->subsampling_convert_state=0;
+                sp->error_in_raw_data_decoding=0;
        }
        while (m>=sp->subsampling_convert_clines)
        {
@@ -792,6 +794,10 @@ OJPEGDecode(TIFF* tif, uint8* buf, tmsize_t cc, uint16 s)
             TIFFErrorExt(tif->tif_clientdata,module,"Cannot decode: decoder not correctly initialized");
             return 0;
         }
+        if( sp->error_in_raw_data_decoding )
+        {
+            return 0;
+        }
        if (sp->libjpeg_jpeg_query_style==0)
        {
                if (OJPEGDecodeRaw(tif,buf,cc)==0)
@@ -831,8 +837,41 @@ OJPEGDecodeRaw(TIFF* tif, uint8* buf, tmsize_t cc)
        {
                if (sp->subsampling_convert_state==0)
                {
+                       const jpeg_decompress_struct* cinfo = &sp->libjpeg_jpeg_decompress_struct;
+                       int width = 0;
+                       int last_col_width = 0;
+                       int jpeg_bytes;
+                       int expected_bytes;
+                       int i;
+                       if (cinfo->MCUs_per_row == 0)
+                       {
+                               sp->error_in_raw_data_decoding = 1;
+                               return 0;
+                       }
+                       for (i = 0; i < cinfo->comps_in_scan; ++i)
+                       {
+                               const jpeg_component_info* info = cinfo->cur_comp_info[i];
+#if JPEG_LIB_VERSION >= 70
+                               width += info->MCU_width * info->DCT_h_scaled_size;
+                               last_col_width += info->last_col_width * info->DCT_h_scaled_size;
+#else
+                               width += info->MCU_width * info->DCT_scaled_size;
+                               last_col_width += info->last_col_width * info->DCT_scaled_size;
+#endif
+                       }
+                       jpeg_bytes = (cinfo->MCUs_per_row - 1) * width + last_col_width;
+                       expected_bytes = sp->subsampling_convert_clinelenout * sp->subsampling_ver * sp->subsampling_hor;
+                       if (jpeg_bytes != expected_bytes)
+                       {
+                               TIFFErrorExt(tif->tif_clientdata,module,"Inconsistent number of MCU in codestream");
+                               sp->error_in_raw_data_decoding = 1;
+                               return(0);
+                       }
                        if (jpeg_read_raw_data_encap(sp,&(sp->libjpeg_jpeg_decompress_struct),sp->subsampling_convert_ycbcrimage,sp->subsampling_ver*8)==0)
+                       {
+                               sp->error_in_raw_data_decoding = 1;
                                return(0);
+                       }
                }
                oy=sp->subsampling_convert_ybuf+sp->subsampling_convert_state*sp->subsampling_ver*sp->subsampling_convert_ylinelen;
                ocb=sp->subsampling_convert_cbbuf+sp->subsampling_convert_state*sp->subsampling_convert_clinelen;
@@ -990,7 +1029,6 @@ OJPEGSubsamplingCorrect(TIFF* tif)
        OJPEGState* sp=(OJPEGState*)tif->tif_data;
        uint8 mh;
        uint8 mv;
-        _TIFFFillStriles( tif );
         
        assert(sp->subsamplingcorrect_done==0);
        if ((tif->tif_dir.td_samplesperpixel!=3) || ((tif->tif_dir.td_photometric!=PHOTOMETRIC_YCBCR) &&
@@ -1046,7 +1084,7 @@ OJPEGReadHeaderInfo(TIFF* tif)
        assert(sp->readheader_done==0);
        sp->image_width=tif->tif_dir.td_imagewidth;
        sp->image_length=tif->tif_dir.td_imagelength;
-       if isTiled(tif)
+       if (isTiled(tif))
        {
                sp->strile_width=tif->tif_dir.td_tilewidth;
                sp->strile_length=tif->tif_dir.td_tilelength;
@@ -1082,6 +1120,12 @@ OJPEGReadHeaderInfo(TIFF* tif)
        }
        if (sp->strile_length<sp->image_length)
        {
+               if (((sp->subsampling_hor!=1) && (sp->subsampling_hor!=2) && (sp->subsampling_hor!=4)) ||
+                   ((sp->subsampling_ver!=1) && (sp->subsampling_ver!=2) && (sp->subsampling_ver!=4)))
+               {
+                       TIFFErrorExt(tif->tif_clientdata,module,"Invalid subsampling values");
+                       return(0);
+               }
                if (sp->strile_length%(sp->subsampling_ver*8)!=0)
                {
                        TIFFErrorExt(tif->tif_clientdata,module,"Incompatible vertical subsampling and image strip/tile length");
@@ -1197,7 +1241,13 @@ OJPEGWriteHeaderInfo(TIFF* tif)
                        sp->subsampling_convert_ybuflen=sp->subsampling_convert_ylinelen*sp->subsampling_convert_ylines;
                        sp->subsampling_convert_cbuflen=sp->subsampling_convert_clinelen*sp->subsampling_convert_clines;
                        sp->subsampling_convert_ycbcrbuflen=sp->subsampling_convert_ybuflen+2*sp->subsampling_convert_cbuflen;
-                       sp->subsampling_convert_ycbcrbuf=_TIFFmalloc(sp->subsampling_convert_ycbcrbuflen);
+                        /* The calloc is not normally necessary, except in some edge/broken cases */
+                        /* for example for a tiled image of height 1 with a tile height of 1 and subsampling_hor=subsampling_ver=2 */
+                        /* In that case, libjpeg will only fill the 8 first lines of the 16 lines */
+                        /* See https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=16844 */
+                        /* Even if this case is allowed (?), its handling is broken because OJPEGPreDecode() should also likely */
+                        /* reset subsampling_convert_state to 0 when changing tile. */
+                       sp->subsampling_convert_ycbcrbuf=_TIFFcalloc(1, sp->subsampling_convert_ycbcrbuflen);
                        if (sp->subsampling_convert_ycbcrbuf==0)
                        {
                                TIFFErrorExt(tif->tif_clientdata,module,"Out of memory");
@@ -1223,10 +1273,11 @@ OJPEGWriteHeaderInfo(TIFF* tif)
                                *m++=sp->subsampling_convert_cbbuf+n*sp->subsampling_convert_clinelen;
                        for (n=0; n<sp->subsampling_convert_clines; n++)
                                *m++=sp->subsampling_convert_crbuf+n*sp->subsampling_convert_clinelen;
-                       sp->subsampling_convert_clinelenout=((sp->strile_width+sp->subsampling_hor-1)/sp->subsampling_hor);
+                       sp->subsampling_convert_clinelenout=sp->strile_width/sp->subsampling_hor + ((sp->strile_width % sp->subsampling_hor) != 0 ? 1 : 0);
                        sp->subsampling_convert_state=0;
+                       sp->error_in_raw_data_decoding=0;
                        sp->bytes_per_line=sp->subsampling_convert_clinelenout*(sp->subsampling_ver*sp->subsampling_hor+2);
-                       sp->lines_per_strile=((sp->strile_length+sp->subsampling_ver-1)/sp->subsampling_ver);
+                       sp->lines_per_strile=sp->strile_length/sp->subsampling_ver + ((sp->strile_length % sp->subsampling_ver) != 0 ? 1 : 0);
                        sp->subsampling_convert_log=1;
                }
        }
@@ -1272,7 +1323,9 @@ OJPEGReadHeaderInfoSec(TIFF* tif)
                }
                else
                {
-                       if ((sp->jpeg_interchange_format_length==0) || (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size))
+                       if ((sp->jpeg_interchange_format_length==0) ||
+                            (sp->jpeg_interchange_format > TIFF_UINT64_MAX - sp->jpeg_interchange_format_length) ||
+                            (sp->jpeg_interchange_format+sp->jpeg_interchange_format_length>sp->file_size))
                                sp->jpeg_interchange_format_length=sp->file_size-sp->jpeg_interchange_format;
                }
        }
@@ -1989,32 +2042,30 @@ OJPEGReadBufferFill(OJPEGState* sp)
                                sp->in_buffer_source=osibsStrile;
                                 break;
                        case osibsStrile:
-                               if (!_TIFFFillStriles( sp->tif ) 
-                                   || sp->tif->tif_dir.td_stripoffset == NULL
-                                   || sp->tif->tif_dir.td_stripbytecount == NULL)
-                                       return 0;
-
                                if (sp->in_buffer_next_strile==sp->in_buffer_strile_count)
                                        sp->in_buffer_source=osibsEof;
                                else
                                {
-                                       sp->in_buffer_file_pos=sp->tif->tif_dir.td_stripoffset[sp->in_buffer_next_strile];
+                                       int err = 0;
+                                       sp->in_buffer_file_pos=TIFFGetStrileOffsetWithErr(sp->tif, sp->in_buffer_next_strile, &err);
+                                       if( err )
+                                               return 0;
                                        if (sp->in_buffer_file_pos!=0)
                                        {
+                                               uint64 bytecount = TIFFGetStrileByteCountWithErr(sp->tif, sp->in_buffer_next_strile, &err);
+                                               if( err )
+                                                       return 0;
                                                if (sp->in_buffer_file_pos>=sp->file_size)
                                                        sp->in_buffer_file_pos=0;
-                                               else if (sp->tif->tif_dir.td_stripbytecount==NULL)
+                                               else if (bytecount==0)
                                                        sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
                                                else
                                                {
-                                                       if (sp->tif->tif_dir.td_stripbytecount == 0) {
-                                                               TIFFErrorExt(sp->tif->tif_clientdata,sp->tif->tif_name,"Strip byte counts are missing");
-                                                               return(0);
-                                                       }
-                                                       sp->in_buffer_file_togo=sp->tif->tif_dir.td_stripbytecount[sp->in_buffer_next_strile];
+                                                       sp->in_buffer_file_togo=bytecount;
                                                        if (sp->in_buffer_file_togo==0)
                                                                sp->in_buffer_file_pos=0;
-                                                       else if (sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size)
+                                                       else if (sp->in_buffer_file_pos > TIFF_UINT64_MAX - sp->in_buffer_file_togo || 
+                                                                sp->in_buffer_file_pos+sp->in_buffer_file_togo>sp->file_size)
                                                                sp->in_buffer_file_togo=sp->file_size-sp->in_buffer_file_pos;
                                                }
                                        }
index 7a9f074..7576bb9 100644 (file)
@@ -25,7 +25,6 @@
 /*
  * TIFF Library.
  */
-
 #include <precomp.h>
 
 /*
@@ -132,6 +131,7 @@ TIFFClientOpen(
        if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
                TIFFErrorExt(clientdata, module,
                    "One of the client procedures is NULL pointer.");
+               _TIFFfree(tif);
                goto bad2;
        }
        tif->tif_readproc = readproc;
@@ -182,6 +182,8 @@ TIFFClientOpen(
         * 'h' read TIFF header only, do not load the first IFD
         * '4' ClassicTIFF for creating a file (default)
         * '8' BigTIFF for creating a file
+         * 'D' enable use of deferred strip/tile offset/bytecount array loading.
+         * 'O' on-demand loading of values instead of whole array loading (implies D)
         *
         * The use of the 'l' and 'b' flags is strongly discouraged.
         * These flags are provided solely because numerous vendors,
@@ -263,7 +265,22 @@ TIFFClientOpen(
                                if (m&O_CREAT)
                                        tif->tif_flags |= TIFF_BIGTIFF;
                                break;
+                       case 'D':
+                               tif->tif_flags |= TIFF_DEFERSTRILELOAD;
+                               break;
+                       case 'O':
+                               if( m == O_RDONLY )
+                                       tif->tif_flags |= (TIFF_LAZYSTRILELOAD | TIFF_DEFERSTRILELOAD);
+                               break;
                }
+
+#ifdef DEFER_STRILE_LOAD
+        /* Compatibility with old DEFER_STRILE_LOAD compilation flag */
+        /* Probably unneeded, since to the best of my knowledge (E. Rouault) */
+        /* GDAL was the only user of this, and will now use the new 'D' flag */
+        tif->tif_flags |= TIFF_DEFERSTRILELOAD;
+#endif
+
        /*
         * Read in TIFF header.
         */
index f464e17..bfeef47 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include <precomp.h>
-
 #ifdef PACKBITS_SUPPORT
 /*
  * TIFF Library.
index 655a12b..203db18 100644 (file)
@@ -90,8 +90,8 @@
 #include "tif_predict.h"
 #include "zlib.h"
 
-//#include <stdio.h>
-//#include <stdlib.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <math.h>
 
 /* Tables for converting to/from 11 bit coded values */
@@ -634,20 +634,16 @@ 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)
 {
-        if( m1 == 0 || m2 > TIFF_TMSIZE_T_MAX / m1 )
-            return 0;
-        return m1 * m2;
+        return _TIFFMultiplySSize(NULL, m1, m2, NULL);
 }
 
 static tmsize_t
 add_ms(tmsize_t m1, tmsize_t m2)
 {
+        assert(m1 >= 0 && m2 >= 0);
        /* if either input is zero, assume overflow already occurred */
        if (m1 == 0 || m2 == 0)
                return 0;
@@ -817,9 +813,7 @@ PixarLogDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
                        TIFFErrorExt(tif->tif_clientdata, module,
                            "Decoding error at scanline %lu, %s",
                            (unsigned long) tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
-                       if (inflateSync(&sp->stream) != Z_OK)
-                               return (0);
-                       continue;
+                       return (0);
                }
                if (state != Z_OK) {
                        TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
@@ -1153,7 +1147,7 @@ PixarLogEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
 
        llen = sp->stride * td->td_imagewidth;
     /* Check against the number of elements (of size uint16) of sp->tbuf */
-    if( n > (tmsize_t)(td->td_rowsperstrip * llen) )
+    if( n > ((tmsize_t)td->td_rowsperstrip * llen) )
     {
         TIFFErrorExt(tif->tif_clientdata, module,
                      "Too many input bytes provided");
index b5a3e8c..50caec3 100644 (file)
@@ -27,7 +27,6 @@
  *
  * Directory Printing Support
  */
-
 #include <precomp.h>
 //#include <stdio.h>
 
@@ -653,8 +652,6 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
        if (tif->tif_tagmethods.printdir)
                (*tif->tif_tagmethods.printdir)(tif, fd, flags);
 
-        _TIFFFillStriles( tif );
-        
        if ((flags & TIFFPRINT_STRIPS) &&
            TIFFFieldSet(tif,FIELD_STRIPOFFSETS)) {
                uint32 s;
@@ -666,13 +663,13 @@ TIFFPrintDirectory(TIFF* tif, FILE* fd, long flags)
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
                        fprintf(fd, "    %3lu: [%8I64u, %8I64u]\n",
                            (unsigned long) s,
-                           td->td_stripoffset ? (unsigned __int64) td->td_stripoffset[s] : 0,
-                           td->td_stripbytecount ? (unsigned __int64) td->td_stripbytecount[s] : 0);
+                           (unsigned __int64) TIFFGetStrileOffset(tif, s),
+                           (unsigned __int64) TIFFGetStrileByteCount(tif, s));
 #else
                        fprintf(fd, "    %3lu: [%8llu, %8llu]\n",
                            (unsigned long) s,
-                           td->td_stripoffset ? (unsigned long long) td->td_stripoffset[s] : 0,
-                           td->td_stripbytecount ? (unsigned long long) td->td_stripbytecount[s] : 0);
+                           (unsigned long long) TIFFGetStrileOffset(tif, s),
+                           (unsigned long long) TIFFGetStrileByteCount(tif, s));
 #endif
        }
 }
index 78c23aa..61e05dc 100644 (file)
@@ -29,9 +29,6 @@
 #include <precomp.h>
 //#include <stdio.h>
 
-#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
-#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
-
 int TIFFFillStrip(TIFF* tif, uint32 strip);
 int TIFFFillTile(TIFF* tif, uint32 tile);
 static int TIFFStartStrip(TIFF* tif, uint32 strip);
@@ -49,6 +46,8 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
 #define THRESHOLD_MULTIPLIER 10
 #define MAX_THRESHOLD (THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * THRESHOLD_MULTIPLIER * INITIAL_THRESHOLD)
 
+#define TIFF_INT64_MAX ((((int64)0x7FFFFFFF) << 32) | 0xFFFFFFFF)
+
 /* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset'
  * Returns 1 in case of success, 0 otherwise. */
 static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
@@ -61,6 +60,22 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
 #endif
         tmsize_t already_read = 0;
 
+
+#if SIZEOF_SIZE_T != 8
+        /* On 32 bit processes, if the request is large enough, check against */
+        /* file size */
+        if( size > 1000 * 1000 * 1000 )
+        {
+            uint64 filesize = TIFFGetFileSize(tif);
+            if( (uint64)size >= filesize )
+            {
+                TIFFErrorExt(tif->tif_clientdata, module,
+                             "Chunk size requested is larger than file size.");
+                return 0;
+            }
+        }
+#endif
+
         /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */
         /* so as to avoid allocating too much memory in case the file is too */
         /* short. We could ask for the file size, but this might be */
@@ -103,6 +118,11 @@ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size,
                 }
                 tif->tif_rawdata = new_rawdata;
             }
+            if( tif->tif_rawdata == NULL )
+            {
+                /* should not happen in practice but helps CoverityScan */
+                return 0;
+            }
 
             bytes_read = TIFFReadFile(tif,
                 tif->tif_rawdata + rawdata_offset + already_read, to_read);
@@ -170,17 +190,14 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
         tmsize_t to_read;
         tmsize_t read_ahead_mod;
         /* tmsize_t bytecountm; */
-        
-        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-            return 0;
-        
+
         /*
          * Expand raw data buffer, if needed, to hold data
          * strip coming from file (perhaps should set upper
          * bound on the size of a buffer we'll use?).
          */
 
-        /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */
+        /* bytecountm=(tmsize_t) TIFFGetStrileByteCount(tif, strip); */
 
         /* Not completely sure where the * 2 comes from, but probably for */
         /* an exponentional growth strategy of tif_rawdatasize */
@@ -224,7 +241,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
         /*
         ** Seek to the point in the file where more data should be read.
         */
-        read_offset = td->td_stripoffset[strip]
+        read_offset = TIFFGetStrileOffset(tif, strip)
                 + tif->tif_rawdataoff + tif->tif_rawdataloaded;
 
         if (!SeekOK(tif, read_offset)) {
@@ -241,10 +258,10 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
                 to_read = read_ahead_mod - unused_data;
         else
                 to_read = tif->tif_rawdatasize - unused_data;
-        if( (uint64) to_read > td->td_stripbytecount[strip] 
+        if( (uint64) to_read > TIFFGetStrileByteCount(tif, strip)
             - tif->tif_rawdataoff - tif->tif_rawdataloaded )
         {
-                to_read = (tmsize_t) td->td_stripbytecount[strip]
+                to_read = (tmsize_t) TIFFGetStrileByteCount(tif, strip)
                         - tif->tif_rawdataoff - tif->tif_rawdataloaded;
         }
 
@@ -283,7 +300,7 @@ TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart )
             /* For JPEG, if there are multiple scans (can generally be known */
             /* with the  read_ahead used), we need to read the whole strip */
             if( tif->tif_dir.td_compression==COMPRESSION_JPEG &&
-                (uint64)tif->tif_rawcc < td->td_stripbytecount[strip] )
+                (uint64)tif->tif_rawcc < TIFFGetStrileByteCount(tif, strip) )
             {
                 if( TIFFJPEGIsFullStripRequired(tif) )
                 {
@@ -342,9 +359,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
          * read it a few lines at a time?
          */
 #if defined(CHUNKY_STRIP_READ_SUPPORT)
-        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-            return 0;
-        whole_strip = tif->tif_dir.td_stripbytecount[strip] < 10
+        whole_strip = TIFFGetStrileByteCount(tif, strip) < 10
                 || isMapped(tif);
         if( td->td_compression == COMPRESSION_LERC ||
             td->td_compression == COMPRESSION_JBIG )
@@ -397,7 +412,7 @@ TIFFSeek(TIFF* tif, uint32 row, uint16 sample )
         else if( !whole_strip )
         {
                 if( ((tif->tif_rawdata + tif->tif_rawdataloaded) - tif->tif_rawcp) < read_ahead 
-                    && (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < td->td_stripbytecount[strip] )
+                    && (uint64) tif->tif_rawdataoff+tif->tif_rawdataloaded < TIFFGetStrileByteCount(tif, strip) )
                 {
                         if( !TIFFFillStripPartial(tif,strip,read_ahead,0) )
                                 return 0;
@@ -594,16 +609,11 @@ static tmsize_t
 TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
     const char* module)
 {
-       TIFFDirectory *td = &tif->tif_dir;
-
-    if (!_TIFFFillStriles( tif ))
-        return ((tmsize_t)(-1));
-        
        assert((tif->tif_flags&TIFF_NOREADRAW)==0);
        if (!isMapped(tif)) {
                tmsize_t cc;
 
-               if (!SeekOK(tif, td->td_stripoffset[strip])) {
+               if (!SeekOK(tif, TIFFGetStrileOffset(tif, strip))) {
                        TIFFErrorExt(tif->tif_clientdata, module,
                            "Seek error at scanline %lu, strip %lu",
                            (unsigned long) tif->tif_row, (unsigned long) strip);
@@ -629,8 +639,8 @@ TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size,
        } else {
                tmsize_t ma = 0;
                tmsize_t n;
-               if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)||
-                    ((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size))
+               if ((TIFFGetStrileOffset(tif, strip) > (uint64)TIFF_TMSIZE_T_MAX)||
+                    ((ma=(tmsize_t)TIFFGetStrileOffset(tif, strip))>tif->tif_size))
                 {
                     n=0;
                 }
@@ -674,12 +684,10 @@ static tmsize_t
 TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip,
                         tmsize_t size, const char* module)
 {
-        TIFFDirectory *td = &tif->tif_dir;
-
         assert( !isMapped(tif) );
         assert((tif->tif_flags&TIFF_NOREADRAW)==0);
 
-        if (!SeekOK(tif, td->td_stripoffset[strip_or_tile])) {
+        if (!SeekOK(tif, TIFFGetStrileOffset(tif, strip_or_tile))) {
             if( is_strip )
             {
                 TIFFErrorExt(tif->tif_clientdata, module,
@@ -715,7 +723,7 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
 {
        static const char module[] = "TIFFReadRawStrip";
        TIFFDirectory *td = &tif->tif_dir;
-       uint64 bytecount;
+       uint64 bytecount64;
        tmsize_t bytecountm;
 
        if (!TIFFCheckRead(tif, 0))
@@ -733,31 +741,23 @@ TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size)
                    "Compression scheme does not support access to raw uncompressed data");
                return ((tmsize_t)(-1));
        }
-       bytecount = td->td_stripbytecount[strip];
-       if ((int64)bytecount <= 0) {
-#if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
-               TIFFErrorExt(tif->tif_clientdata, module,
-                            "%I64u: Invalid strip byte count, strip %lu",
-                            (unsigned __int64) bytecount,
-                            (unsigned long) strip);
-#else
-               TIFFErrorExt(tif->tif_clientdata, module,
-                            "%llu: Invalid strip byte count, strip %lu",
-                            (unsigned long long) bytecount,
-                            (unsigned long) strip);
-#endif
-               return ((tmsize_t)(-1));
-       }
-       bytecountm = (tmsize_t)bytecount;
-       if ((uint64)bytecountm!=bytecount) {
-               TIFFErrorExt(tif->tif_clientdata, module, "Integer overflow");
+       bytecount64 = TIFFGetStrileByteCount(tif, strip);
+       if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64)
+               bytecountm = size;
+       else
+               bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module);
+       if( bytecountm == 0 ) {
                return ((tmsize_t)(-1));
        }
-       if (size != (tmsize_t)(-1) && size < bytecountm)
-               bytecountm = size;
        return (TIFFReadRawStrip1(tif, strip, buf, bytecountm, module));
 }
 
+TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
+static uint64 NoSantizeSubUInt64(uint64 a, uint64 b)
+{
+    return a - b;
+}
+
 /*
  * Read the specified strip and setup for decoding. The data buffer is
  * expanded, as necessary, to hold the strip's data.
@@ -768,13 +768,10 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
        static const char module[] = "TIFFFillStrip";
        TIFFDirectory *td = &tif->tif_dir;
 
-        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-            return 0;
-
        if ((tif->tif_flags&TIFF_NOREADRAW)==0)
        {
-               uint64 bytecount = td->td_stripbytecount[strip];
-               if ((int64)bytecount <= 0) {
+               uint64 bytecount = TIFFGetStrileByteCount(tif, strip);
+               if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) {
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
                        TIFFErrorExt(tif->tif_clientdata, module,
                                "Invalid strip byte count %I64u, strip %lu",
@@ -801,7 +798,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
                            (bytecount - 4096) / 10 > (uint64)stripsize  )
                        {
                                uint64 newbytecount = (uint64)stripsize * 10 + 4096;
-                               if( (int64)newbytecount >= 0 )
+                               if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX )
                                {
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
                                        TIFFWarningExt(tif->tif_clientdata, module,
@@ -826,13 +823,13 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
                         * We must check for overflow, potentially causing
                         * an OOB read. Instead of simple
                         *
-                        *  td->td_stripoffset[strip]+bytecount > tif->tif_size
+                        *  TIFFGetStrileOffset(tif, strip)+bytecount > tif->tif_size
                         *
                         * comparison (which can overflow) we do the following
                         * two comparisons:
                         */
                        if (bytecount > (uint64)tif->tif_size ||
-                           td->td_stripoffset[strip] > (uint64)tif->tif_size - bytecount) {
+                           TIFFGetStrileOffset(tif, strip) > (uint64)tif->tif_size - bytecount) {
                                /*
                                 * This error message might seem strange, but
                                 * it's what would happen if a read were done
@@ -844,7 +841,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
                                        "Read error on strip %lu; "
                                        "got %I64u bytes, expected %I64u",
                                        (unsigned long) strip,
-                                       (unsigned __int64) tif->tif_size - td->td_stripoffset[strip],
+                                       (unsigned __int64) NoSantizeSubUInt64(tif->tif_size, TIFFGetStrileOffset(tif, strip)),
                                        (unsigned __int64) bytecount);
 #else
                                TIFFErrorExt(tif->tif_clientdata, module,
@@ -852,7 +849,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
                                        "Read error on strip %lu; "
                                        "got %llu bytes, expected %llu",
                                        (unsigned long) strip,
-                                       (unsigned long long) tif->tif_size - td->td_stripoffset[strip],
+                                       (unsigned long long) NoSantizeSubUInt64(tif->tif_size, TIFFGetStrileOffset(tif, strip)),
                                        (unsigned long long) bytecount);
 #endif
                                tif->tif_curstrip = NOSTRIP;
@@ -881,7 +878,7 @@ TIFFFillStrip(TIFF* tif, uint32 strip)
                        }
                        tif->tif_flags &= ~TIFF_MYBUFFER;
                        tif->tif_rawdatasize = (tmsize_t)bytecount;
-                       tif->tif_rawdata = tif->tif_base + (tmsize_t)td->td_stripoffset[strip];
+                       tif->tif_rawdata = tif->tif_base + (tmsize_t)TIFFGetStrileOffset(tif, strip);
                         tif->tif_rawdataoff = 0;
                         tif->tif_rawdataloaded = (tmsize_t) bytecount;
 
@@ -1096,16 +1093,11 @@ _TIFFReadEncodedTileAndAllocBuffer(TIFF* tif, uint32 tile,
 static tmsize_t
 TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module)
 {
-       TIFFDirectory *td = &tif->tif_dir;
-
-    if (!_TIFFFillStriles( tif ))
-        return ((tmsize_t)(-1));
-
        assert((tif->tif_flags&TIFF_NOREADRAW)==0);
        if (!isMapped(tif)) {
                tmsize_t cc;
 
-               if (!SeekOK(tif, td->td_stripoffset[tile])) {
+               if (!SeekOK(tif, TIFFGetStrileOffset(tif, tile))) {
                        TIFFErrorExt(tif->tif_clientdata, module,
                            "Seek error at row %lu, col %lu, tile %lu",
                            (unsigned long) tif->tif_row,
@@ -1135,9 +1127,9 @@ TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* m
        } else {
                tmsize_t ma,mb;
                tmsize_t n;
-               ma=(tmsize_t)td->td_stripoffset[tile];
+               ma=(tmsize_t)TIFFGetStrileOffset(tif, tile);
                mb=ma+size;
-               if ((td->td_stripoffset[tile] > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size))
+               if ((TIFFGetStrileOffset(tif, tile) > (uint64)TIFF_TMSIZE_T_MAX)||(ma>tif->tif_size))
                        n=0;
                else if ((mb<ma)||(mb<size)||(mb>tif->tif_size))
                        n=tif->tif_size-ma;
@@ -1193,13 +1185,12 @@ TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size)
                "Compression scheme does not support access to raw uncompressed data");
                return ((tmsize_t)(-1));
        }
-       bytecount64 = td->td_stripbytecount[tile];
-       if (size != (tmsize_t)(-1) && (uint64)size < bytecount64)
-               bytecount64 = (uint64)size;
-       bytecountm = (tmsize_t)bytecount64;
-       if ((uint64)bytecountm!=bytecount64)
-       {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
+       bytecount64 = TIFFGetStrileByteCount(tif, tile);
+       if (size != (tmsize_t)(-1) && (uint64)size <= bytecount64)
+               bytecountm = size;
+       else
+               bytecountm = _TIFFCastUInt64ToSSize(tif, bytecount64, module);
+       if( bytecountm == 0 ) {
                return ((tmsize_t)(-1));
        }
        return (TIFFReadRawTile1(tif, tile, buf, bytecountm, module));
@@ -1215,13 +1206,10 @@ TIFFFillTile(TIFF* tif, uint32 tile)
        static const char module[] = "TIFFFillTile";
        TIFFDirectory *td = &tif->tif_dir;
 
-        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-            return 0;
-
        if ((tif->tif_flags&TIFF_NOREADRAW)==0)
        {
-               uint64 bytecount = td->td_stripbytecount[tile];
-               if ((int64)bytecount <= 0) {
+               uint64 bytecount = TIFFGetStrileByteCount(tif, tile);
+               if( bytecount == 0 || bytecount > (uint64)TIFF_INT64_MAX ) {
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
                        TIFFErrorExt(tif->tif_clientdata, module,
                                "%I64u: Invalid tile byte count, tile %lu",
@@ -1248,7 +1236,7 @@ TIFFFillTile(TIFF* tif, uint32 tile)
                            (bytecount - 4096) / 10 > (uint64)stripsize  )
                        {
                                uint64 newbytecount = (uint64)stripsize * 10 + 4096;
-                               if( (int64)newbytecount >= 0 )
+                               if( newbytecount == 0 || newbytecount > (uint64)TIFF_INT64_MAX )
                                {
 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
                                        TIFFWarningExt(tif->tif_clientdata, module,
@@ -1273,13 +1261,13 @@ TIFFFillTile(TIFF* tif, uint32 tile)
                         * We must check for overflow, potentially causing
                         * an OOB read. Instead of simple
                         *
-                        *  td->td_stripoffset[tile]+bytecount > tif->tif_size
+                        *  TIFFGetStrileOffset(tif, tile)+bytecount > tif->tif_size
                         *
                         * comparison (which can overflow) we do the following
                         * two comparisons:
                         */
                        if (bytecount > (uint64)tif->tif_size ||
-                           td->td_stripoffset[tile] > (uint64)tif->tif_size - bytecount) {
+                           TIFFGetStrileOffset(tif, tile) > (uint64)tif->tif_size - bytecount) {
                                tif->tif_curtile = NOTILE;
                                return (0);
                        }
@@ -1308,7 +1296,7 @@ TIFFFillTile(TIFF* tif, uint32 tile)
 
                        tif->tif_rawdatasize = (tmsize_t)bytecount;
                        tif->tif_rawdata =
-                               tif->tif_base + (tmsize_t)td->td_stripoffset[tile];
+                               tif->tif_base + (tmsize_t)TIFFGetStrileOffset(tif, tile);
                         tif->tif_rawdataoff = 0;
                         tif->tif_rawdataloaded = (tmsize_t) bytecount;
                        tif->tif_flags |= TIFF_BUFFERMMAP;
@@ -1367,7 +1355,8 @@ TIFFFillTile(TIFF* tif, uint32 tile)
                         tif->tif_rawdataoff = 0;
                         tif->tif_rawdataloaded = bytecountm;
                         
-                       if (!isFillOrder(tif, td->td_fillorder) &&
+                       if (tif->tif_rawdata != NULL &&
+                            !isFillOrder(tif, td->td_fillorder) &&
                            (tif->tif_flags & TIFF_NOBITREV) == 0)
                                TIFFReverseBits(tif->tif_rawdata,
                                                 tif->tif_rawdataloaded);
@@ -1434,9 +1423,6 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
 {
        TIFFDirectory *td = &tif->tif_dir;
 
-        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-            return 0;
-
        if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
                if (!(*tif->tif_setupdecode)(tif))
                        return (0);
@@ -1457,7 +1443,7 @@ TIFFStartStrip(TIFF* tif, uint32 strip)
                if( tif->tif_rawdataloaded > 0 )
                        tif->tif_rawcc = tif->tif_rawdataloaded;
                else
-                       tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[strip];
+                       tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, strip);
        }
        return ((*tif->tif_predecode)(tif,
                        (uint16)(strip / td->td_stripsperimage)));
@@ -1474,9 +1460,6 @@ TIFFStartTile(TIFF* tif, uint32 tile)
        TIFFDirectory *td = &tif->tif_dir;
         uint32 howmany32;
 
-        if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount)
-                return 0;
-
        if ((tif->tif_flags & TIFF_CODERSETUP) == 0) {
                if (!(*tif->tif_setupdecode)(tif))
                        return (0);
@@ -1507,7 +1490,7 @@ TIFFStartTile(TIFF* tif, uint32 tile)
                if( tif->tif_rawdataloaded > 0 )
                        tif->tif_rawcc = tif->tif_rawdataloaded;
                else
-                       tif->tif_rawcc = (tmsize_t)td->td_stripbytecount[tile];
+                       tif->tif_rawcc = (tmsize_t)TIFFGetStrileByteCount(tif, tile);
        }
        return ((*tif->tif_predecode)(tif,
                        (uint16)(tile/td->td_stripsperimage)));
@@ -1522,13 +1505,100 @@ TIFFCheckRead(TIFF* tif, int tiles)
        }
        if (tiles ^ isTiled(tif)) {
                TIFFErrorExt(tif->tif_clientdata, tif->tif_name, tiles ?
-                   "Can not read tiles from a stripped image" :
+                   "Can not read tiles from a striped image" :
                    "Can not read scanlines from a tiled image");
                return (0);
        }
        return (1);
 }
 
+/* Use the provided input buffer (inbuf, insize) and decompress it into
+ * (outbuf, outsize).
+ * This function replaces the use of TIFFReadEncodedStrip()/TIFFReadEncodedTile()
+ * when the user can provide the buffer for the input data, for example when
+ * he wants to avoid libtiff to read the strile offset/count values from the
+ * [Strip|Tile][Offsets/ByteCounts] array.
+ * inbuf content must be writable (if bit reversal is needed)
+ * Returns 1 in case of success, 0 otherwise.
+ */
+int      TIFFReadFromUserBuffer(TIFF* tif, uint32 strile,
+                                void* inbuf, tmsize_t insize,
+                                void* outbuf, tmsize_t outsize)
+{
+    static const char module[] = "TIFFReadFromUserBuffer";
+    TIFFDirectory *td = &tif->tif_dir;
+    int ret = 1;
+    uint32 old_tif_flags = tif->tif_flags;
+    tmsize_t old_rawdatasize = tif->tif_rawdatasize;
+    void* old_rawdata = tif->tif_rawdata;
+
+    if (tif->tif_mode == O_WRONLY) {
+        TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "File not open for reading");
+        return 0;
+    }
+    if (tif->tif_flags&TIFF_NOREADRAW)
+    {
+        TIFFErrorExt(tif->tif_clientdata, module,
+                "Compression scheme does not support access to raw uncompressed data");
+        return 0;
+    }
+
+    tif->tif_flags &= ~TIFF_MYBUFFER;
+    tif->tif_flags |= TIFF_BUFFERMMAP;
+    tif->tif_rawdatasize = insize;
+    tif->tif_rawdata = inbuf;
+    tif->tif_rawdataoff = 0;
+    tif->tif_rawdataloaded = insize;
+
+    if (!isFillOrder(tif, td->td_fillorder) &&
+        (tif->tif_flags & TIFF_NOBITREV) == 0)
+    {
+        TIFFReverseBits(inbuf, insize);
+    }
+
+    if( TIFFIsTiled(tif) )
+    {
+        if( !TIFFStartTile(tif, strile) ||
+            !(*tif->tif_decodetile)(tif, (uint8*) outbuf, outsize, 
+                                    (uint16)(strile/td->td_stripsperimage)) )
+        {
+            ret = 0;
+        }
+    }
+    else
+    {
+        uint32 rowsperstrip=td->td_rowsperstrip;
+        uint32 stripsperplane;
+        if (rowsperstrip>td->td_imagelength)
+            rowsperstrip=td->td_imagelength;
+        stripsperplane= TIFFhowmany_32_maxuint_compat(td->td_imagelength, rowsperstrip);
+        if( !TIFFStartStrip(tif, strile) ||
+            !(*tif->tif_decodestrip)(tif, (uint8*) outbuf, outsize, 
+                                     (uint16)(strile/stripsperplane)) )
+        {
+            ret = 0;
+        }
+    }
+    if( ret )
+    {
+        (*tif->tif_postdecode)(tif, (uint8*) outbuf, outsize);
+    }
+
+    if (!isFillOrder(tif, td->td_fillorder) &&
+        (tif->tif_flags & TIFF_NOBITREV) == 0)
+    {
+        TIFFReverseBits(inbuf, insize);
+    }
+
+    tif->tif_flags = old_tif_flags;
+    tif->tif_rawdatasize = old_rawdatasize;
+    tif->tif_rawdata = old_rawdata;
+    tif->tif_rawdataoff = 0;
+    tif->tif_rawdataloaded = 0;
+
+    return ret;
+}
+
 void
 _TIFFNoPostDecode(TIFF* tif, uint8* buf, tmsize_t cc)
 {
index d468714..0e4ed85 100644 (file)
@@ -27,7 +27,6 @@
  *
  * Strip-organized Image Support Routines.
  */
-
 #include <precomp.h>
 
 /*
@@ -130,15 +129,8 @@ TIFFVStripSize(TIFF* tif, uint32 nrows)
 {
        static const char module[] = "TIFFVStripSize";
        uint64 m;
-       tmsize_t n;
        m=TIFFVStripSize64(tif,nrows);
-       n=(tmsize_t)m;
-       if ((uint64)n!=m)
-       {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
-               n=0;
-       }
-       return(n);
+        return _TIFFCastUInt64ToSSize(tif, m, module);
 }
 
 /*
@@ -148,8 +140,7 @@ uint64
 TIFFRawStripSize64(TIFF* tif, uint32 strip)
 {
        static const char module[] = "TIFFRawStripSize64";
-       TIFFDirectory* td = &tif->tif_dir;
-       uint64 bytecount = td->td_stripbytecount[strip];
+       uint64 bytecount = TIFFGetStrileByteCount(tif, strip);
 
        if (bytecount == 0)
        {
@@ -212,15 +203,8 @@ TIFFStripSize(TIFF* tif)
 {
        static const char module[] = "TIFFStripSize";
        uint64 m;
-       tmsize_t n;
        m=TIFFStripSize64(tif);
-       n=(tmsize_t)m;
-       if ((uint64)n!=m)
-       {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
-               n=0;
-       }
-       return(n);
+       return _TIFFCastUInt64ToSSize(tif, m, module);
 }
 
 /*
@@ -331,14 +315,8 @@ TIFFScanlineSize(TIFF* tif)
 {
        static const char module[] = "TIFFScanlineSize";
        uint64 m;
-       tmsize_t n;
        m=TIFFScanlineSize64(tif);
-       n=(tmsize_t)m;
-       if ((uint64)n!=m) {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
-               n=0;
-       }
-       return(n);
+       return _TIFFCastUInt64ToSSize(tif, m, module);
 }
 
 /*
@@ -367,15 +345,8 @@ TIFFRasterScanlineSize(TIFF* tif)
 {
        static const char module[] = "TIFFRasterScanlineSize";
        uint64 m;
-       tmsize_t n;
        m=TIFFRasterScanlineSize64(tif);
-       n=(tmsize_t)m;
-       if ((uint64)n!=m)
-       {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer arithmetic overflow");
-               n=0;
-       }
-       return(n);
+       return _TIFFCastUInt64ToSSize(tif, m, module);
 }
 
 /* vim: set ts=8 sts=8 sw=8 noet: */
index cec8770..08a2d2b 100644 (file)
@@ -123,17 +123,17 @@ ThunderDecode(TIFF* tif, uint8* op, tmsize_t maxpixels)
                        break;
                case THUNDER_2BITDELTAS:        /* 2-bit deltas */
                        if ((delta = ((n >> 4) & 3)) != DELTA2_SKIP)
-                               SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+                               SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta]));
                        if ((delta = ((n >> 2) & 3)) != DELTA2_SKIP)
-                               SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+                               SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta]));
                        if ((delta = (n & 3)) != DELTA2_SKIP)
-                               SETPIXEL(op, lastpixel + twobitdeltas[delta]);
+                               SETPIXEL(op, (unsigned)((int)lastpixel + twobitdeltas[delta]));
                        break;
                case THUNDER_3BITDELTAS:        /* 3-bit deltas */
                        if ((delta = ((n >> 3) & 7)) != DELTA3_SKIP)
-                               SETPIXEL(op, lastpixel + threebitdeltas[delta]);
+                               SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta]));
                        if ((delta = (n & 7)) != DELTA3_SKIP)
-                               SETPIXEL(op, lastpixel + threebitdeltas[delta]);
+                               SETPIXEL(op, (unsigned)((int)lastpixel + threebitdeltas[delta]));
                        break;
                case THUNDER_RAW:               /* raw data */
                        SETPIXEL(op, n);
index 36a0000..77126af 100644 (file)
@@ -27,7 +27,6 @@
  *
  * Tiled Image Support Routines.
  */
-
 #include <precomp.h>
 
 /*
@@ -182,15 +181,8 @@ TIFFTileRowSize(TIFF* tif)
 {
        static const char module[] = "TIFFTileRowSize";
        uint64 m;
-       tmsize_t n;
        m=TIFFTileRowSize64(tif);
-       n=(tmsize_t)m;
-       if ((uint64)n!=m)
-       {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
-               n=0;
-       }
-       return(n);
+       return _TIFFCastUInt64ToSSize(tif, m, module);
 }
 
 /*
@@ -249,15 +241,8 @@ TIFFVTileSize(TIFF* tif, uint32 nrows)
 {
        static const char module[] = "TIFFVTileSize";
        uint64 m;
-       tmsize_t n;
        m=TIFFVTileSize64(tif,nrows);
-       n=(tmsize_t)m;
-       if ((uint64)n!=m)
-       {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
-               n=0;
-       }
-       return(n);
+       return _TIFFCastUInt64ToSSize(tif, m, module);
 }
 
 /*
@@ -273,15 +258,8 @@ TIFFTileSize(TIFF* tif)
 {
        static const char module[] = "TIFFTileSize";
        uint64 m;
-       tmsize_t n;
        m=TIFFTileSize64(tif);
-       n=(tmsize_t)m;
-       if ((uint64)n!=m)
-       {
-               TIFFErrorExt(tif->tif_clientdata,module,"Integer overflow");
-               n=0;
-       }
-       return(n);
+       return _TIFFCastUInt64ToSSize(tif, m, module);
 }
 
 /*
index 0139cdb..f0ccf27 100644 (file)
@@ -21,7 +21,6 @@
  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  * OF THIS SOFTWARE.
  */
-
 #include <precomp.h>
 
 static const char TIFFVersion[] = TIFFLIB_VERSION_STR;
index a002f48..22665f2 100644 (file)
@@ -349,6 +349,12 @@ TWebPSetupEncode(TIFF* tif)
 
   sp->state |= LSTATE_INIT_ENCODE;
 
+  if (!WebPPictureInit(&sp->sPicture)) {
+    TIFFErrorExt(tif->tif_clientdata, module,
+        "Error initializing WebP picture.");
+    return 0;
+  }
+
   if (!WebPConfigInitInternal(&sp->sEncoderConfig, WEBP_PRESET_DEFAULT,
                               sp->quality_level,
                               WEBP_ENCODER_ABI_VERSION)) {
@@ -357,9 +363,13 @@ TWebPSetupEncode(TIFF* tif)
     return 0;
   }
 
-#if WEBP_ENCODER_ABI_VERSION >= 0x0100
-  sp->sEncoderConfig.lossless = sp->lossless;
-#endif
+  // WebPConfigInitInternal above sets lossless to false
+  #if WEBP_ENCODER_ABI_VERSION >= 0x0100
+    sp->sEncoderConfig.lossless = sp->lossless;
+    if (sp->lossless) {
+      sp->sPicture.use_argb = 1;
+    }
+  #endif
 
   if (!WebPValidateConfig(&sp->sEncoderConfig)) {
     TIFFErrorExt(tif->tif_clientdata, module,
@@ -367,12 +377,6 @@ TWebPSetupEncode(TIFF* tif)
     return 0;
   }
 
-  if (!WebPPictureInit(&sp->sPicture)) {
-    TIFFErrorExt(tif->tif_clientdata, module,
-        "Error initializing WebP picture.");
-    return 0;
-  }
-
   return 1;
 }
 
@@ -415,6 +419,12 @@ TWebPPreEncode(TIFF* tif, uint16 s)
   /* set up buffer for raw data */
   /* given above check and that nSamples <= 4, buffer_size is <= 1 GB */
   sp->buffer_size = segment_width * segment_height * sp->nSamples;
+  
+  if (sp->pBuffer != NULL) {
+      _TIFFfree(sp->pBuffer);
+      sp->pBuffer = NULL;    
+  }
+  
   sp->pBuffer = _TIFFmalloc(sp->buffer_size);
   if( !sp->pBuffer) {
       TIFFErrorExt(tif->tif_clientdata, module, "Cannot allocate buffer");
@@ -460,7 +470,7 @@ TWebPPostEncode(TIFF* tif)
                     "WebPPictureImportRGB() failed");
       return 0;
   }
-
+  
   if (!WebPEncode(&sp->sEncoderConfig, &sp->sPicture)) {
 
 #if WEBP_ENCODER_ABI_VERSION >= 0x0100
@@ -540,15 +550,13 @@ TWebPCleanup(TIFF* tif)
   }
   
   if (sp->pBuffer != NULL) {
-    _TIFFfree(sp->pBuffer);
-    sp->pBuffer = NULL;
+      _TIFFfree(sp->pBuffer);
+      sp->pBuffer = NULL;    
   }
 
-  if (tif->tif_data) {
-    _TIFFfree(tif->tif_data);
-    tif->tif_data = NULL;
-  }
-  
+  _TIFFfree(tif->tif_data);
+  tif->tif_data = NULL;
+
   _TIFFSetDefaultCompressionState(tif);
 }
 
@@ -570,6 +578,9 @@ TWebPVSetField(TIFF* tif, uint32 tag, va_list ap)
   case TIFFTAG_WEBP_LOSSLESS:
     #if WEBP_ENCODER_ABI_VERSION >= 0x0100
     sp->lossless = va_arg(ap, int);
+    if (sp->lossless){
+      sp->quality_level = 100.0f;      
+    }
     return 1;
     #else
       TIFFErrorExt(tif->tif_clientdata, module,
index 32603fe..7b5a011 100644 (file)
@@ -27,7 +27,6 @@
  *
  * Scanline-oriented Write Support
  */
-
 #include <precomp.h>
 //#include <stdio.h>
 
@@ -129,10 +128,10 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
                tif->tif_rawcc = 0;
                tif->tif_rawcp = tif->tif_rawdata;
 
-               if( td->td_stripbytecount[strip] > 0 )
+               if( td->td_stripbytecount_p[strip] > 0 )
                {
                        /* if we are writing over existing tiles, zero length */
-                       td->td_stripbytecount[strip] = 0;
+                       td->td_stripbytecount_p[strip] = 0;
 
                        /* this forces TIFFAppendToStrip() to do a seek */
                        tif->tif_curoff = 0;
@@ -177,6 +176,32 @@ TIFFWriteScanline(TIFF* tif, void* buf, uint32 row, uint16 sample)
        return (status);
 }
 
+/* Make sure that at the first attempt of rewriting a tile/strip, we will have */
+/* more bytes available in the output buffer than the previous byte count, */
+/* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
+/* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
+static int _TIFFReserveLargeEnoughWriteBuffer(TIFF* tif, uint32 strip_or_tile)
+{
+    TIFFDirectory *td = &tif->tif_dir;
+    if( td->td_stripbytecount_p[strip_or_tile] > 0 )
+    {
+        /* The +1 is to ensure at least one extra bytes */
+        /* The +4 is because the LZW encoder flushes 4 bytes before the limit */
+        uint64 safe_buffer_size = (uint64)(td->td_stripbytecount_p[strip_or_tile] + 1 + 4);
+        if( tif->tif_rawdatasize <= (tmsize_t)safe_buffer_size )
+        {
+            if( !(TIFFWriteBufferSetup(tif, NULL,
+                (tmsize_t)TIFFroundup_64(safe_buffer_size, 1024))) )
+                return 0;
+        }
+
+        /* Force TIFFAppendToStrip() to consider placing data at end
+            of file. */
+        tif->tif_curoff = 0;
+    }
+    return 1;
+}
+
 /*
  * Encode the supplied data and write it to the
  * specified strip.
@@ -223,6 +248,13 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
         tif->tif_flags |= TIFF_BUF4WRITE;
        tif->tif_curstrip = strip;
 
+       if( !_TIFFReserveLargeEnoughWriteBuffer(tif, strip) ) {
+            return ((tmsize_t)(-1));
+        }
+
+        tif->tif_rawcc = 0;
+        tif->tif_rawcp = tif->tif_rawdata;
+
         if (td->td_stripsperimage == 0) {
                 TIFFErrorExt(tif->tif_clientdata, module, "Zero strips per image");
                 return ((tmsize_t) -1);
@@ -235,27 +267,6 @@ TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc)
                tif->tif_flags |= TIFF_CODERSETUP;
        }
 
-       if( td->td_stripbytecount[strip] > 0 )
-        {
-            /* Make sure that at the first attempt of rewriting the tile, we will have */
-            /* more bytes available in the output buffer than the previous byte count, */
-            /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
-            /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
-            if( tif->tif_rawdatasize <= (tmsize_t)td->td_stripbytecount[strip] )
-            {
-                if( !(TIFFWriteBufferSetup(tif, NULL,
-                    (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[strip] + 1), 1024))) )
-                    return ((tmsize_t)(-1));
-            }
-
-           /* Force TIFFAppendToStrip() to consider placing data at end
-               of file. */
-            tif->tif_curoff = 0;
-        }
-
-    tif->tif_rawcc = 0;
-    tif->tif_rawcp = tif->tif_rawdata;
-
        tif->tif_flags &= ~TIFF_POSTENCODE;
 
     /* shortcut to avoid an extra memcpy() */
@@ -403,22 +414,8 @@ TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc)
         tif->tif_flags |= TIFF_BUF4WRITE;
        tif->tif_curtile = tile;
 
-       if( td->td_stripbytecount[tile] > 0 )
-        {
-            /* Make sure that at the first attempt of rewriting the tile, we will have */
-            /* more bytes available in the output buffer than the previous byte count, */
-            /* so that TIFFAppendToStrip() will detect the overflow when it is called the first */
-            /* time if the new compressed tile is bigger than the older one. (GDAL #4771) */
-            if( tif->tif_rawdatasize <= (tmsize_t) td->td_stripbytecount[tile] )
-            {
-                if( !(TIFFWriteBufferSetup(tif, NULL,
-                    (tmsize_t)TIFFroundup_64((uint64)(td->td_stripbytecount[tile] + 1), 1024))) )
-                    return ((tmsize_t)(-1));
-            }
-
-           /* Force TIFFAppendToStrip() to consider placing data at end
-               of file. */
-            tif->tif_curoff = 0;
+        if( !_TIFFReserveLargeEnoughWriteBuffer(tif, tile) ) {
+            return ((tmsize_t)(-1));
         }
 
        tif->tif_rawcc = 0;
@@ -538,20 +535,20 @@ TIFFSetupStrips(TIFF* tif)
        td->td_nstrips = td->td_stripsperimage;
        if (td->td_planarconfig == PLANARCONFIG_SEPARATE)
                td->td_stripsperimage /= td->td_samplesperpixel;
-       td->td_stripoffset = (uint64 *)
+       td->td_stripoffset_p = (uint64 *)
             _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
                              "for \"StripOffsets\" array");
-       td->td_stripbytecount = (uint64 *)
+       td->td_stripbytecount_p = (uint64 *)
             _TIFFCheckMalloc(tif, td->td_nstrips, sizeof (uint64),
                              "for \"StripByteCounts\" array");
-       if (td->td_stripoffset == NULL || td->td_stripbytecount == NULL)
+       if (td->td_stripoffset_p == NULL || td->td_stripbytecount_p == NULL)
                return (0);
        /*
         * Place data at the end-of-file
         * (by setting offsets to zero).
         */
-       _TIFFmemset(td->td_stripoffset, 0, td->td_nstrips*sizeof (uint64));
-       _TIFFmemset(td->td_stripbytecount, 0, td->td_nstrips*sizeof (uint64));
+       _TIFFmemset(td->td_stripoffset_p, 0, td->td_nstrips*sizeof (uint64));
+       _TIFFmemset(td->td_stripbytecount_p, 0, td->td_nstrips*sizeof (uint64));
        TIFFSetFieldBit(tif, FIELD_STRIPOFFSETS);
        TIFFSetFieldBit(tif, FIELD_STRIPBYTECOUNTS);
        return (1);
@@ -573,7 +570,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
        }
        if (tiles ^ isTiled(tif)) {
                TIFFErrorExt(tif->tif_clientdata, module, tiles ?
-                   "Can not write tiles to a stripped image" :
+                   "Can not write tiles to a striped image" :
                    "Can not write scanlines to a tiled image");
                return (0);
        }
@@ -611,7 +608,7 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
                        return (0);
                }
        }
-       if (tif->tif_dir.td_stripoffset == NULL && !TIFFSetupStrips(tif)) {
+       if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) {
                tif->tif_dir.td_nstrips = 0;
                TIFFErrorExt(tif->tif_clientdata, module, "No space for %s arrays",
                    isTiled(tif) ? "tile" : "strip");
@@ -629,6 +626,20 @@ TIFFWriteCheck(TIFF* tif, int tiles, const char* module)
        if (tif->tif_scanlinesize == 0)
                return (0);
        tif->tif_flags |= TIFF_BEENWRITING;
+
+        if( tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
+            tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
+            tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
+            tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
+            tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0 &&
+            !(tif->tif_flags & TIFF_DIRTYDIRECT)  )
+        {
+            TIFFForceStrileArrayWriting(tif);
+        }
+
        return (1);
 }
 
@@ -685,9 +696,9 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
        uint64* new_stripbytecount;
 
        assert(td->td_planarconfig == PLANARCONFIG_CONTIG);
-       new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset,
+       new_stripoffset = (uint64*)_TIFFrealloc(td->td_stripoffset_p,
                (td->td_nstrips + delta) * sizeof (uint64));
-       new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount,
+       new_stripbytecount = (uint64*)_TIFFrealloc(td->td_stripbytecount_p,
                (td->td_nstrips + delta) * sizeof (uint64));
        if (new_stripoffset == NULL || new_stripbytecount == NULL) {
                if (new_stripoffset)
@@ -698,11 +709,11 @@ TIFFGrowStrips(TIFF* tif, uint32 delta, const char* module)
                TIFFErrorExt(tif->tif_clientdata, module, "No space to expand strip arrays");
                return (0);
        }
-       td->td_stripoffset = new_stripoffset;
-       td->td_stripbytecount = new_stripbytecount;
-       _TIFFmemset(td->td_stripoffset + td->td_nstrips,
+       td->td_stripoffset_p = new_stripoffset;
+       td->td_stripbytecount_p = new_stripbytecount;
+       _TIFFmemset(td->td_stripoffset_p + td->td_nstrips,
                    0, delta*sizeof (uint64));
-       _TIFFmemset(td->td_stripbytecount + td->td_nstrips,
+       _TIFFmemset(td->td_stripbytecount_p + td->td_nstrips,
                    0, delta*sizeof (uint64));
        td->td_nstrips += delta;
         tif->tif_flags |= TIFF_DIRTYDIRECT;
@@ -721,12 +732,12 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
        uint64 m;
         int64 old_byte_count = -1;
 
-       if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) {
+       if (td->td_stripoffset_p[strip] == 0 || tif->tif_curoff == 0) {
             assert(td->td_nstrips > 0);
 
-            if( td->td_stripbytecount[strip] != 0 
-                && td->td_stripoffset[strip] != 0 
-                && td->td_stripbytecount[strip] >= (uint64) cc )
+            if( td->td_stripbytecount_p[strip] != 0 
+                && td->td_stripoffset_p[strip] != 0 
+                && td->td_stripbytecount_p[strip] >= (uint64) cc )
             {
                 /* 
                  * There is already tile data on disk, and the new tile
@@ -735,7 +746,7 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
                  * more data to append to this strip before we are done
                  * depending on how we are getting called.
                  */
-                if (!SeekOK(tif, td->td_stripoffset[strip])) {
+                if (!SeekOK(tif, td->td_stripoffset_p[strip])) {
                     TIFFErrorExt(tif->tif_clientdata, module,
                                  "Seek error at scanline %lu",
                                  (unsigned long)tif->tif_row);
@@ -748,17 +759,17 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
                  * Seek to end of file, and set that as our location to 
                  * write this strip.
                  */
-                td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END);
+                td->td_stripoffset_p[strip] = TIFFSeekFile(tif, 0, SEEK_END);
                 tif->tif_flags |= TIFF_DIRTYSTRIP;
             }
 
-            tif->tif_curoff = td->td_stripoffset[strip];
+            tif->tif_curoff = td->td_stripoffset_p[strip];
 
             /*
              * We are starting a fresh strip/tile, so set the size to zero.
              */
-            old_byte_count = td->td_stripbytecount[strip];
-            td->td_stripbytecount[strip] = 0;
+            old_byte_count = td->td_stripbytecount_p[strip];
+            td->td_stripbytecount_p[strip] = 0;
        }
 
        m = tif->tif_curoff+cc;
@@ -775,9 +786,9 @@ TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc)
                    return (0);
        }
        tif->tif_curoff = m;
-       td->td_stripbytecount[strip] += cc;
+       td->td_stripbytecount_p[strip] += cc;
 
-        if( (int64) td->td_stripbytecount[strip] != old_byte_count )
+        if( (int64) td->td_stripbytecount_p[strip] != old_byte_count )
             tif->tif_flags |= TIFF_DIRTYSTRIP;
             
        return (1);
index 6dc64b2..c30aefd 100644 (file)
@@ -23,7 +23,6 @@
  */
 
 #include <precomp.h>
-
 #ifdef ZIP_SUPPORT
 /*
  * TIFF Library.
@@ -48,7 +47,7 @@
 #include "tif_predict.h"
 #include "zlib.h"
 
-//#include <stdio.h>
+#include <stdio.h>
 
 /*
  * Sigh, ZLIB_VERSION is defined as a string so there's no
@@ -125,7 +124,6 @@ ZIPSetupDecode(TIFF* tif)
 static int
 ZIPPreDecode(TIFF* tif, uint16 s)
 {
-       static const char module[] = "ZIPPreDecode";
        ZIPState* sp = DecoderState(tif);
 
        (void) s;
@@ -139,12 +137,7 @@ ZIPPreDecode(TIFF* tif, uint16 s)
            we need to simplify this code to reflect a ZLib that is likely updated
            to deal with 8byte memory sizes, though this code will respond
            appropriately even before we simplify it */
-       sp->stream.avail_in = (uInt) tif->tif_rawcc;
-       if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
-       {
-               TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
-               return (0);
-       }
+       sp->stream.avail_in = (uint64)tif->tif_rawcc < 0xFFFFFFFFU ? (uInt) tif->tif_rawcc : 0xFFFFFFFFU;
        return (inflateReset(&sp->stream) == Z_OK);
 }
 
@@ -159,46 +152,43 @@ ZIPDecode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
        assert(sp->state == ZSTATE_INIT_DECODE);
 
         sp->stream.next_in = tif->tif_rawcp;
-       sp->stream.avail_in = (uInt) tif->tif_rawcc;
         
        sp->stream.next_out = op;
        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
            to deal with 8byte memory sizes, though this code will respond
            appropriately even before we simplify it */
-       sp->stream.avail_out = (uInt) occ;
-       if ((tmsize_t)sp->stream.avail_out != occ)
-       {
-               TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
-               return (0);
-       }
        do {
-               int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
+                int state;
+                uInt avail_in_before = (uint64)tif->tif_rawcc <= 0xFFFFFFFFU ? (uInt)tif->tif_rawcc : 0xFFFFFFFFU;
+                uInt avail_out_before = (uint64)occ < 0xFFFFFFFFU ? (uInt) occ : 0xFFFFFFFFU;
+                sp->stream.avail_in = avail_in_before;
+                sp->stream.avail_out = avail_out_before;
+               state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
+               tif->tif_rawcc -= (avail_in_before - sp->stream.avail_in);
+                occ -= (avail_out_before - sp->stream.avail_out);
                if (state == Z_STREAM_END)
                        break;
                if (state == Z_DATA_ERROR) {
                        TIFFErrorExt(tif->tif_clientdata, module,
                            "Decoding error at scanline %lu, %s",
                             (unsigned long) tif->tif_row, SAFE_MSG(sp));
-                       if (inflateSync(&sp->stream) != Z_OK)
-                               return (0);
-                       continue;
+                       return (0);
                }
                if (state != Z_OK) {
                        TIFFErrorExt(tif->tif_clientdata, module, 
                                     "ZLib error: %s", SAFE_MSG(sp));
                        return (0);
                }
-       } while (sp->stream.avail_out > 0);
-       if (sp->stream.avail_out != 0) {
+       } while (occ > 0);
+       if (occ != 0) {
                TIFFErrorExt(tif->tif_clientdata, module,
                    "Not enough data at scanline %lu (short " TIFF_UINT64_FORMAT " bytes)",
-                   (unsigned long) tif->tif_row, (TIFF_UINT64_T) sp->stream.avail_out);
+                   (unsigned long) tif->tif_row, (TIFF_UINT64_T) occ);
                return (0);
        }
 
         tif->tif_rawcp = sp->stream.next_in;
-        tif->tif_rawcc = sp->stream.avail_in;
 
        return (1);
 }
@@ -230,7 +220,6 @@ ZIPSetupEncode(TIFF* tif)
 static int
 ZIPPreEncode(TIFF* tif, uint16 s)
 {
-       static const char module[] = "ZIPPreEncode";
        ZIPState *sp = EncoderState(tif);
 
        (void) s;
@@ -243,12 +232,7 @@ ZIPPreEncode(TIFF* tif, uint16 s)
            we need to simplify this code to reflect a ZLib that is likely updated
            to deal with 8byte memory sizes, though this code will respond
            appropriately even before we simplify it */
-       sp->stream.avail_out = (uInt)tif->tif_rawdatasize;
-       if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
-       {
-               TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
-               return (0);
-       }
+       sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
        return (deflateReset(&sp->stream) == Z_OK);
 }
 
@@ -270,13 +254,9 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
            we need to simplify this code to reflect a ZLib that is likely updated
            to deal with 8byte memory sizes, though this code will respond
            appropriately even before we simplify it */
-       sp->stream.avail_in = (uInt) cc;
-       if ((tmsize_t)sp->stream.avail_in != cc)
-       {
-               TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
-               return (0);
-       }
        do {
+                uInt avail_in_before = (uint64)cc <= 0xFFFFFFFFU ? (uInt)cc : 0xFFFFFFFFU;
+                sp->stream.avail_in = avail_in_before;
                if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
                        TIFFErrorExt(tif->tif_clientdata, module, 
                                     "Encoder error: %s",
@@ -287,9 +267,10 @@ ZIPEncode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
                        tif->tif_rawcc = tif->tif_rawdatasize;
                        TIFFFlushData1(tif);
                        sp->stream.next_out = tif->tif_rawdata;
-                       sp->stream.avail_out = (uInt) tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in ZIPPreEncode */
+                       sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
                }
-       } while (sp->stream.avail_in > 0);
+               cc -= (avail_in_before - sp->stream.avail_in);
+       } while (cc > 0);
        return (1);
 }
 
@@ -315,7 +296,7 @@ ZIPPostEncode(TIFF* tif)
                                tif->tif_rawcc =  tif->tif_rawdatasize - sp->stream.avail_out;
                                TIFFFlushData1(tif);
                                sp->stream.next_out = tif->tif_rawdata;
-                               sp->stream.avail_out = (uInt) tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in ZIPPreEncode */
+                               sp->stream.avail_out = (uint64)tif->tif_rawdatasize <= 0xFFFFFFFFU ? (uInt)tif->tif_rawdatasize : 0xFFFFFFFFU;
                        }
                        break;
                default:
index 7863c68..c9c06ee 100644 (file)
@@ -79,7 +79,7 @@ Used Version: 9c
 Website: http://www.ijg.org/
 
 Title: libtiff
-Used Version: 4.0.10
+Used Version: 4.1.0
 Website: http://www.simplesystems.org/libtiff/
 
 Title: mbed TLS
index b2f5e69..e7f0667 100644 (file)
@@ -58,6 +58,7 @@ typedef struct {
                uint32 toff_long;
                uint64 toff_long8;
        } tdir_offset;          /* either offset or the data itself if fits */
+       uint8  tdir_ignore;     /* flag status to ignore tag when parsing tags in tif_dirread.c */
 } TIFFDirEntry;
 
 /*
@@ -97,13 +98,14 @@ typedef struct {
         * number of striles */
        uint32  td_stripsperimage;  
        uint32  td_nstrips;              /* size of offset & bytecount arrays */
-       uint64* td_stripoffset;
-       uint64* td_stripbytecount;
+       uint64* td_stripoffset_p;        /* should be accessed with TIFFGetStrileOffset */
+       uint64* td_stripbytecount_p;     /* should be accessed with TIFFGetStrileByteCount */
+        uint32  td_stripoffsetbyteallocsize; /* number of elements currently allocated for td_stripoffset/td_stripbytecount. Only used if TIFF_LAZYSTRILELOAD is set */
+#ifdef STRIPBYTECOUNTSORTED_UNUSED
        int     td_stripbytecountsorted; /* is the bytecount array sorted ascending? */
-#if defined(DEFER_STRILE_LOAD)
+#endif
         TIFFDirEntry td_stripoffset_entry;    /* for deferred loading */
         TIFFDirEntry td_stripbytecount_entry; /* for deferred loading */
-#endif
        uint16  td_nsubifd;
        uint64* td_subifd;
        /* YCbCr parameters */
@@ -118,6 +120,8 @@ typedef struct {
 
        int     td_customValueCount;
         TIFFTagValue *td_customValues;
+
+        unsigned char td_deferstrilearraywriting; /* see TIFFDeferStrileArrayWriting() */
 } TIFFDirectory;
 
 /*
index e806549..198481d 100644 (file)
@@ -94,12 +94,7 @@ typedef void* tdata_t;          /* image data ref */
 
 #if defined(USE_WIN32_FILEIO)
 # define VC_EXTRALEAN
-#ifdef __REACTOS__
-# define WIN32_NO_STATUS
-# include <windef.h>
-#else /* __REACTOS__ */
 # include <windows.h>
-#endif /* __REACTOS__ */
 # ifdef __WIN32__
 DECLARE_HANDLE(thandle_t);     /* Win32 file handle */
 # else
@@ -416,6 +411,8 @@ extern int TIFFWriteDirectory(TIFF *);
 extern int TIFFWriteCustomDirectory(TIFF *, uint64 *);
 extern int TIFFCheckpointDirectory(TIFF *);
 extern int TIFFRewriteDirectory(TIFF *);
+extern int TIFFDeferStrileArrayWriting(TIFF *);
+extern int TIFFForceStrileArrayWriting(TIFF* );
 
 #if defined(c_plusplus) || defined(__cplusplus)
 extern void TIFFPrintDirectory(TIFF*, FILE*, long = 0);
@@ -473,6 +470,9 @@ extern tmsize_t TIFFReadEncodedStrip(TIFF* tif, uint32 strip, void* buf, tmsize_
 extern tmsize_t TIFFReadRawStrip(TIFF* tif, uint32 strip, void* buf, tmsize_t size);  
 extern tmsize_t TIFFReadEncodedTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size);  
 extern tmsize_t TIFFReadRawTile(TIFF* tif, uint32 tile, void* buf, tmsize_t size);  
+extern int      TIFFReadFromUserBuffer(TIFF* tif, uint32 strile,
+                                       void* inbuf, tmsize_t insize,
+                                       void* outbuf, tmsize_t outsize);
 extern tmsize_t TIFFWriteEncodedStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc);
 extern tmsize_t TIFFWriteRawStrip(TIFF* tif, uint32 strip, void* data, tmsize_t cc);  
 extern tmsize_t TIFFWriteEncodedTile(TIFF* tif, uint32 tile, void* data, tmsize_t cc);  
@@ -493,6 +493,11 @@ extern void TIFFSwabArrayOfDouble(double* dp, tmsize_t n);
 extern void TIFFReverseBits(uint8* cp, tmsize_t n);
 extern const unsigned char* TIFFGetBitRevTable(int);
 
+extern uint64 TIFFGetStrileOffset(TIFF *tif, uint32 strile);
+extern uint64 TIFFGetStrileByteCount(TIFF *tif, uint32 strile);
+extern uint64 TIFFGetStrileOffsetWithErr(TIFF *tif, uint32 strile, int *pbErr);
+extern uint64 TIFFGetStrileByteCountWithErr(TIFF *tif, uint32 strile, int *pbErr);
+
 #ifdef LOGLUV_PUBLIC
 #define U_NEU          0.210526316
 #define V_NEU          0.473684211
index 186c291..45a7932 100644 (file)
@@ -77,6 +77,19 @@ extern int snprintf(char* str, size_t size, const char* format, ...);
 #define        FALSE   0
 #endif
 
+#define TIFF_SIZE_T_MAX ((size_t) ~ ((size_t)0))
+#define TIFF_TMSIZE_T_MAX (tmsize_t)(TIFF_SIZE_T_MAX >> 1)
+
+/*
+ * Largest 32-bit unsigned integer value.
+ */
+#define TIFF_UINT32_MAX 0xFFFFFFFFU
+
+/*
+ * Largest 64-bit unsigned integer value.
+ */
+#define TIFF_UINT64_MAX (((uint64)(TIFF_UINT32_MAX)) << 32 | TIFF_UINT32_MAX)
+
 typedef struct client_info {
     struct client_info *next;
     void *data;
@@ -127,6 +140,9 @@ struct tiff {
         #define TIFF_DIRTYSTRIP 0x200000U /* stripoffsets/stripbytecount dirty*/
         #define TIFF_PERSAMPLE  0x400000U /* get/set per sample tags as arrays */
         #define TIFF_BUFFERMMAP 0x800000U /* read buffer (tif_rawdata) points into mmap() memory */
+        #define TIFF_DEFERSTRILELOAD 0x1000000U /* defer strip/tile offset/bytecount array loading. */
+        #define TIFF_LAZYSTRILELOAD  0x2000000U /* lazy/ondemand loading of strip/tile offset/bytecount values. Only used if TIFF_DEFERSTRILELOAD is set and in read-only mode */
+        #define TIFF_CHOPPEDUPARRAYS 0x4000000U /* set when allocChoppedUpStripArrays() has modified strip array */
        uint64               tif_diroff;       /* file offset of current directory */
        uint64               tif_nextdiroff;   /* file offset of following directory */
        uint64*              tif_dirlist;      /* list of offsets to already seen directories to prevent IFD looping */
@@ -258,7 +274,7 @@ struct tiff {
 #define TIFFhowmany8_64(x) (((x)&0x07)?((uint64)(x)>>3)+1:(uint64)(x)>>3)
 #define TIFFroundup_64(x, y) (TIFFhowmany_64(x,y)*(y))
 
-/* Safe multiply which returns zero if there is an integer overflow */
+/* Safe multiply which returns zero if there is an *unsigned* integer overflow. This macro is not safe for *signed* integer types */
 #define TIFFSafeMultiply(t,v,m) ((((t)(m) != (t)0) && (((t)(((v)*(m))/(m))) == (t)(v))) ? (t)((v)*(m)) : (t)0)
 
 #define TIFFmax(A,B) ((A)>(B)?(A):(B))
@@ -368,12 +384,16 @@ extern TIFFErrorHandlerExt _TIFFerrorHandlerExt;
 
 extern uint32 _TIFFMultiply32(TIFF*, uint32, uint32, const char*);
 extern uint64 _TIFFMultiply64(TIFF*, uint64, uint64, const char*);
+extern tmsize_t _TIFFMultiplySSize(TIFF*, tmsize_t, tmsize_t, const char*);
+extern tmsize_t _TIFFCastUInt64ToSSize(TIFF*, uint64, const char*);
 extern void* _TIFFCheckMalloc(TIFF*, tmsize_t, tmsize_t, const char*);
 extern void* _TIFFCheckRealloc(TIFF*, void*, tmsize_t, tmsize_t, const char*);
 
 extern double _TIFFUInt64ToDouble(uint64);
 extern float _TIFFUInt64ToFloat(uint64);
 
+extern float _TIFFClampDoubleToFloat(double);
+
 extern tmsize_t
 _TIFFReadEncodedStripAndAllocBuffer(TIFF* tif, uint32 strip,
                                     void **buf, tmsize_t bufsizetoalloc,
index 403d61b..aa3f613 100644 (file)
@@ -1,4 +1,4 @@
-#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.0.10\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
+#define TIFFLIB_VERSION_STR "LIBTIFF, Version 4.1.0\nCopyright (c) 1988-1996 Sam Leffler\nCopyright (c) 1991-1996 Silicon Graphics, Inc."
 /*
  * This define can be used in code that requires
  * compilation-related definitions specific to a
@@ -6,4 +6,4 @@
  * version checking should be done based on the
  * string returned by TIFFGetVersion.
  */
-#define TIFFLIB_VERSION 20181110
+#define TIFFLIB_VERSION 20191103