[gimp/wip/wormnest/xcf-parasite] app: fix #3928 GIMP cannot open .xcf




commit 4a7f1d6dab2dd3a59a9d8a0fec89a4d870a01e17
Author: Jacob Boerema <jgboerema gmail com>
Date:   Mon Apr 4 17:33:29 2022 -0400

    app: fix #3928 GIMP cannot open .xcf
    
    GIMP stopped trying to read the XCF as soon as an invalid parasite was
    encountered. However, in this specific case only the parasite data is
    invalid, while the rest of the image is not corrupt.
    
    Instead of terminating when we see a corrupt parasite, we skip to the
    offset after the parasite. This may still be corrupt, but we can handle
    that correctly, see e.g. the XCF in bugzilla issue 685086, which was
    the reason of some of the previous changes.
    
    Additionally:
    - We add some logging to make it easier to handle future issues in this
      area.
    - We add tests for a NULL parasite name, and for reading a different
      amount of parasite data than we expected. In both cases we return
      NULL instead of a parasite.

 app/xcf/xcf-load.c | 37 ++++++++++++++++++++++++++++++++-----
 1 file changed, 32 insertions(+), 5 deletions(-)
---
diff --git a/app/xcf/xcf-load.c b/app/xcf/xcf-load.c
index e1bfd5c2ce..ac9c4ea248 100644
--- a/app/xcf/xcf-load.c
+++ b/app/xcf/xcf-load.c
@@ -1112,7 +1112,15 @@ xcf_load_image_props (XcfInfo   *info,
                 GError       *error = NULL;
 
                 if (! p)
-                  return FALSE;
+                  {
+                    gimp_message (info->gimp, G_OBJECT (info->progress),
+                                  GIMP_MESSAGE_WARNING,
+                                  "Invalid image parasite found. "
+                                  "Possibly corrupt XCF file.");
+
+                    xcf_seek_pos (info, base + prop_size, NULL);
+                    continue;
+                  }
 
                 if (! gimp_image_parasite_validate (image, p, &error))
                   {
@@ -2091,6 +2099,8 @@ xcf_load_prop (XcfInfo  *info,
   if (G_UNLIKELY (xcf_read_int32 (info, (guint32 *) prop_size, 1) != 4))
     return FALSE;
 
+  GIMP_LOG (XCF, "prop type=%d size=%u", *prop_type, *prop_size);
+
   return TRUE;
 }
 
@@ -2968,16 +2978,18 @@ xcf_load_tile_zlib (XcfInfo       *info,
 static GimpParasite *
 xcf_load_parasite (XcfInfo *info)
 {
-  GimpParasite *parasite;
+  GimpParasite *parasite = NULL;
   gchar        *name;
   guint32       flags;
-  guint32       size;
+  guint32       size, size_read;
   gpointer      data;
 
   xcf_read_string (info, &name,  1);
   xcf_read_int32  (info, &flags, 1);
   xcf_read_int32  (info, &size,  1);
 
+  GIMP_LOG (XCF, "Parasite name: %s, flags: %d, size: %d", name, flags, size);
+
   if (size > MAX_XCF_PARASITE_DATA_LEN)
     {
       g_printerr ("Maximum parasite data length (%ld bytes) exceeded. "
@@ -2986,10 +2998,25 @@ xcf_load_parasite (XcfInfo *info)
       return NULL;
     }
 
+  if (!name)
+    {
+      g_printerr ("Parasite has no name! Possibly corrupt XCF file.\n");
+      return NULL;
+    }
+
   data = g_new (gchar, size);
-  xcf_read_int8 (info, data, size);
+  size_read = xcf_read_int8 (info, data, size);
 
-  parasite = gimp_parasite_new (name, flags, size, data);
+  if (size_read != size)
+    {
+      g_printerr ("Incorrect parasite data size: read %u bytes instead of %u. "
+                  "Possibly corrupt XCF file.\n",
+                  size_read, size);
+    }
+  else
+    {
+      parasite = gimp_parasite_new (name, flags, size, data);
+    }
 
   g_free (name);
   g_free (data);


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