[gimp/gimp-2-10] plug-ins: improvement of TIFF loading when TIFFNumberOfDirectories()…



commit 7ec030814a1d578c240a82df95a6177dd6c262c8
Author: Jehan <jehan girinstud io>
Date:   Mon Nov 16 16:10:25 2020 +0100

    plug-ins: improvement of TIFF loading when TIFFNumberOfDirectories()…
    
    … fails.
    My previous commit was just assuming there is one page when the libtiff
    function fails. But thinking a bit more on this, there are 2 edge cases
    even here:
    
    - If the image is actually really corrupted to the point there are no
      TIFF directories to read.
    - If there are actually more available directories. It would be much
      better if GIMP were able to salvage them from a broken file.
    
    To handle these cases, I actually count manually the number of
    directories by looping with TIFFSetDirectory() (which still works fine
    on our minimal image). I use 65535 as a max value because in libtiff's
    TIFFNumberOfDirectories() implementation, it says this is the max value
    (even though I couldn't confirm this in the spec; there is a "Number of
    Directory Entries" on 2 bytes, but this is about various fields for each
    directories, not a number of directories; still anyway this is already a
    huge number and since libtiff won't likely be able to handle directories
    over this limit, not need to go over either).
    
    I am also adding a test in the end so that we can output an appropriate
    message if we actually failed to read any data from the TIFF (whether or
    not TIFFNumberOfDirectories() succeeded, when we actually tried to read
    the contents, we couldn't).
    
    (cherry picked from commit 9a90eefe1f112b0be9af01159d9b102b832f05d0)

 plug-ins/file-tiff/file-tiff-load.c | 45 ++++++++++++++++++++++++++++++++-----
 1 file changed, 40 insertions(+), 5 deletions(-)
---
diff --git a/plug-ins/file-tiff/file-tiff-load.c b/plug-ins/file-tiff/file-tiff-load.c
index 7abf3b8cf2..3ab80c6438 100644
--- a/plug-ins/file-tiff/file-tiff-load.c
+++ b/plug-ins/file-tiff/file-tiff-load.c
@@ -197,10 +197,33 @@ load_image (GFile        *file,
        * It seems we might be able to rescue some data even though the
        * TIFF is possibly syntactically wrong.
        */
-      pages.n_pages = 1;
-      g_message (_("TIFF '%s' does not contain any directories."
-                   " Attempting to load the file assuming 1 page."),
-                 gimp_file_get_utf8_name (file));
+
+      /* libtiff says max number of directory is 65535. */
+      for (li = 0; li < 65536; li++)
+        {
+          if (TIFFSetDirectory (tif, li) == 0)
+            break;
+        }
+      pages.n_pages = li;
+      if (pages.n_pages == 0)
+        {
+          TIFFClose (tif);
+          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                       _("TIFF '%s' does not contain any directories"),
+                       gimp_file_get_utf8_name (file));
+
+          return GIMP_PDB_EXECUTION_ERROR;
+        }
+
+      TIFFSetDirectory (tif, 0);
+      g_message (ngettext ("TIFF '%s' directory count by header failed "
+                           "though there seems to be %d page."
+                           " Attempting to load the file with this assumption.",
+                           "TIFF '%s' directory count by header failed "
+                           "though there seem to be %d pages."
+                           " Attempting to load the file with this assumption.",
+                           pages.n_pages),
+                 gimp_file_get_utf8_name (file), pages.n_pages);
     }
 
   pages.pages = NULL;
@@ -229,7 +252,9 @@ load_image (GFile        *file,
           gushort  extra;
           gushort *extra_types;
 
-          TIFFSetDirectory (tif, li);
+          if (TIFFSetDirectory (tif, li) == 0)
+            continue;
+
           TIFFGetFieldDefaulted (tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
           if (! TIFFGetField (tif, TIFFTAG_PHOTOMETRIC, &photomet))
             {
@@ -1281,6 +1306,16 @@ load_image (GFile        *file,
     }
   else
     {
+      if (! (*image))
+        {
+          TIFFClose (tif);
+          g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED,
+                       _("No data could be read from TIFF '%s'. The file is probably corrupted."),
+                       gimp_file_get_utf8_name (file));
+
+          return GIMP_PDB_EXECUTION_ERROR;
+        }
+
       if (pages.keep_empty_space)
         {
           /* unfortunately we have no idea about empty space


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]