Imported Upstream version 4.0.10 into tizen
[platform/upstream/tiff.git] / libtiff / tif_dirread.c
index 5e62e81..e80a3b1 100755 (executable)
@@ -1,5 +1,3 @@
-/* $Id: tif_dirread.c,v 1.218 2017-09-09 21:44:42 erouault Exp $ */
-
 /*
  * Copyright (c) 1988-1997 Sam Leffler
  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
@@ -167,6 +165,7 @@ static int TIFFFetchStripThing(TIFF* tif, TIFFDirEntry* dir, uint32 nstrips, uin
 static int TIFFFetchSubjectDistance(TIFF*, TIFFDirEntry*);
 static void ChopUpSingleUncompressedStrip(TIFF*);
 static uint64 TIFFReadUInt64(const uint8 *value);
+static int _TIFFGetMaxColorChannels(uint16 photometric);
 
 static int _TIFFFillStrilesInternal( TIFF *tif, int loadStripByteCount );
 
@@ -776,7 +775,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryIfd8(TIFF* tif, TIFFDirEntry* di
 static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc(
                     TIFF* tif, uint64 offset, tmsize_t size, void** pdest)
 {
-#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8
+#if SIZEOF_SIZE_T == 8
         tmsize_t threshold = INITIAL_THRESHOLD;
 #endif
         tmsize_t already_read = 0;
@@ -797,7 +796,7 @@ static enum TIFFReadDirEntryErr TIFFReadDirEntryDataAndRealloc(
             void* new_dest;
             tmsize_t bytes_read;
             tmsize_t to_read = size - already_read;
-#if SIZEOF_VOIDP == 8 || SIZEOF_SIZE_T == 8
+#if SIZEOF_SIZE_T == 8
             if( to_read >= threshold && threshold < MAX_THRESHOLD )
             {
                 to_read = threshold;
@@ -3507,6 +3506,35 @@ static void TIFFReadDirEntryOutputErr(TIFF* tif, enum TIFFReadDirEntryErr err, c
 }
 
 /*
+ * Return the maximum number of color channels specified for a given photometric
+ * type. 0 is returned if photometric type isn't supported or no default value
+ * is defined by the specification.
+ */
+static int _TIFFGetMaxColorChannels( uint16 photometric )
+{
+    switch (photometric) {
+       case PHOTOMETRIC_PALETTE:
+       case PHOTOMETRIC_MINISWHITE:
+       case PHOTOMETRIC_MINISBLACK:
+            return 1;
+       case PHOTOMETRIC_YCBCR:
+       case PHOTOMETRIC_RGB:
+       case PHOTOMETRIC_CIELAB:
+       case PHOTOMETRIC_LOGLUV:
+       case PHOTOMETRIC_ITULAB:
+       case PHOTOMETRIC_ICCLAB:
+            return 3;
+       case PHOTOMETRIC_SEPARATED:
+       case PHOTOMETRIC_MASK:
+            return 4;
+       case PHOTOMETRIC_LOGL:
+       case PHOTOMETRIC_CFA:
+       default:
+            return 0;
+    }
+}
+
+/*
  * Read the next TIFF directory from a file and convert it to the internal
  * format. We read directories sequentially.
  */
@@ -3522,6 +3550,7 @@ TIFFReadDirectory(TIFF* tif)
        uint32 fii=FAILED_FII;
         toff_t nextdiroff;
     int bitspersample_read = FALSE;
+        int color_channels;
 
        tif->tif_diroff=tif->tif_nextdiroff;
        if (!TIFFCheckDirOffset(tif,tif->tif_nextdiroff))
@@ -4026,6 +4055,37 @@ TIFFReadDirectory(TIFF* tif)
                        }
                }
        }
+
+       /*
+        * Make sure all non-color channels are extrasamples.
+        * If it's not the case, define them as such.
+        */
+        color_channels = _TIFFGetMaxColorChannels(tif->tif_dir.td_photometric);
+        if (color_channels && tif->tif_dir.td_samplesperpixel - tif->tif_dir.td_extrasamples > color_channels) {
+                uint16 old_extrasamples;
+                uint16 *new_sampleinfo;
+
+                TIFFWarningExt(tif->tif_clientdata,module, "Sum of Photometric type-related "
+                    "color channels and ExtraSamples doesn't match SamplesPerPixel. "
+                    "Defining non-color channels as ExtraSamples.");
+
+                old_extrasamples = tif->tif_dir.td_extrasamples;
+                tif->tif_dir.td_extrasamples = (uint16) (tif->tif_dir.td_samplesperpixel - color_channels);
+
+                // sampleinfo should contain information relative to these new extra samples
+                new_sampleinfo = (uint16*) _TIFFcalloc(tif->tif_dir.td_extrasamples, sizeof(uint16));
+                if (!new_sampleinfo) {
+                    TIFFErrorExt(tif->tif_clientdata, module, "Failed to allocate memory for "
+                                "temporary new sampleinfo array (%d 16 bit elements)",
+                                tif->tif_dir.td_extrasamples);
+                    goto bad;
+                }
+
+                memcpy(new_sampleinfo, tif->tif_dir.td_sampleinfo, old_extrasamples * sizeof(uint16));
+                _TIFFsetShortArray(&tif->tif_dir.td_sampleinfo, new_sampleinfo, tif->tif_dir.td_extrasamples);
+                _TIFFfree(new_sampleinfo);
+        }
+
        /*
         * Verify Palette image has a Colormap.
         */
@@ -4881,17 +4941,18 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
                                err=TIFFReadDirEntryByteArray(tif,dp,&data);
                                if (err==TIFFReadDirEntryErrOk)
                                {
-                                       uint8* ma;
-                                       uint32 mb;
+                                       uint32 mb = 0;
                                        int n;
-                                       ma=data;
-                                       mb=0;
-                                       while (mb<(uint32)dp->tdir_count)
+                                       if (data != NULL)
                                        {
-                                               if (*ma==0)
-                                                       break;
-                                               ma++;
-                                               mb++;
+                                           uint8* ma = data;
+                                           while (mb<(uint32)dp->tdir_count)
+                                           {
+                                                   if (*ma==0)
+                                                           break;
+                                                   ma++;
+                                                   mb++;
+                                           }
                                        }
                                        if (mb+1<(uint32)dp->tdir_count)
                                                TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" contains null byte in value; value incorrectly truncated during reading due to implementation limitations",fip->field_name);
@@ -5141,11 +5202,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
                                        if (err==TIFFReadDirEntryErrOk)
                                        {
                                                int m;
-                        if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
-                        {
-                            TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
-                            data[dp->tdir_count-1] = '\0';
-                        }
+                                               if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
+                                               {
+                                                   TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
+                                                   data[dp->tdir_count-1] = '\0';
+                                               }
                                                m=TIFFSetField(tif,dp->tdir_tag,(uint16)(dp->tdir_count),data);
                                                if (data!=0)
                                                        _TIFFfree(data);
@@ -5318,11 +5379,11 @@ TIFFFetchNormalTag(TIFF* tif, TIFFDirEntry* dp, int recover)
                                if (err==TIFFReadDirEntryErrOk)
                                {
                                        int m;
-                    if( dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
-                    {
-                        TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
-                        data[dp->tdir_count-1] = '\0';
-                    }
+                                       if( data != 0 && dp->tdir_count > 0 && data[dp->tdir_count-1] != '\0' )
+                                       {
+                                           TIFFWarningExt(tif->tif_clientdata,module,"ASCII value for tag \"%s\" does not end in null byte. Forcing it to be null",fip->field_name);
+                                            data[dp->tdir_count-1] = '\0';
+                                       }
                                        m=TIFFSetField(tif,dp->tdir_tag,(uint32)(dp->tdir_count),data);
                                        if (data!=0)
                                                _TIFFfree(data);
@@ -5698,6 +5759,16 @@ ChopUpSingleUncompressedStrip(TIFF* tif)
         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 &&
+            (offset >= TIFFGetFileSize(tif) ||
+             stripbytes > (TIFFGetFileSize(tif) - offset) / (nstrips - 1)) )
+        {
+            return;
+        }
+
        newcounts = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),
                                "for chopped \"StripByteCounts\" array");
        newoffsets = (uint64*) _TIFFCheckMalloc(tif, nstrips, sizeof (uint64),