[gimp] libgimpbase: fix #8025 Slow loading of XCF files...



commit cadf48529944d002b395c068043ecdd9100144c7
Author: Jacob Boerema <jgboerema gmail com>
Date:   Mon Apr 4 16:52:10 2022 -0400

    libgimpbase: fix #8025 Slow loading of XCF files...
    
    with many Xmp.photoshop.DocumentAncestors tags
    
    This is similar to #7464, but in this case the XMP metadata was already
    included in an XCF image.
    
    We check for the occurrence of Xmp.photoshop.DocumentAncestors and stop
    handling values when there are more than a 1000.
    
    It would be easier to just check length for all tags and always
    ignore when there are more than a 1000 values.
    But in that case we would need to be sure there are no valid reasons for
    tags to occur more than a 1000 times. So let's just limit it to this
    specific tag.

 libgimpbase/gimpmetadata.c | 43 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 32 insertions(+), 11 deletions(-)
---
diff --git a/libgimpbase/gimpmetadata.c b/libgimpbase/gimpmetadata.c
index 62a9299448..a0531588b1 100644
--- a/libgimpbase/gimpmetadata.c
+++ b/libgimpbase/gimpmetadata.c
@@ -590,6 +590,7 @@ typedef struct
 {
   gchar         name[1024];
   gboolean      base64;
+  gboolean      excessive_message_shown;
   GimpMetadata *metadata;
 } GimpMetadataParseData;
 
@@ -710,19 +711,38 @@ gimp_metadata_deserialize_text (GMarkupParseContext  *context,
             {
               guint length = g_strv_length (values);
 
-              values = g_renew (gchar *, values, length + 2);
-              values[length]     = value;
-              values[length + 1] = NULL;
+              if (length > 1000 &&
+                  ! g_strcmp0 (parse_data->name, "Xmp.photoshop.DocumentAncestors"))
+                {
+                  /* Issue #8025, see also #7464 Some XCF images can have huge
+                   * amounts of this tag, apparently due to a bug in PhotoShop.
+                   * This makes deserializing it in the way we currently do
+                   * too slow. Until we can change this let's ignore everything
+                   * but the first 1000 values when serializing. */
 
-              gexiv2_metadata_try_set_tag_multiple (g2_metadata,
-                                                    parse_data->name,
-                                                    (const gchar **) values,
-                                                    &error);
-              if (error)
+                  if (! parse_data->excessive_message_shown)
+                    {
+                      g_message ("Excessive number of Xmp.photoshop.DocumentAncestors tags found. "
+                                 "Only keeping the first 1000 values.");
+                      parse_data->excessive_message_shown = TRUE;
+                    }
+                }
+              else
                 {
-                  g_warning ("%s: failed to set multiple metadata '%s': %s\n",
-                             G_STRFUNC, parse_data->name, error->message);
-                  g_clear_error (&error);
+                  values = g_renew (gchar *, values, length + 2);
+                  values[length]     = value;
+                  values[length + 1] = NULL;
+
+                  gexiv2_metadata_try_set_tag_multiple (g2_metadata,
+                                                        parse_data->name,
+                                                        (const gchar **) values,
+                                                        &error);
+                  if (error)
+                    {
+                      g_warning ("%s: failed to set multiple metadata '%s': %s\n",
+                                 G_STRFUNC, parse_data->name, error->message);
+                      g_clear_error (&error);
+                    }
                 }
               g_strfreev (values);
             }
@@ -775,6 +795,7 @@ gimp_metadata_deserialize (const gchar *metadata_xml)
   metadata = gimp_metadata_new ();
 
   parse_data.metadata = metadata;
+  parse_data.excessive_message_shown = FALSE;
 
   markup_parser.start_element = gimp_metadata_deserialize_start_element;
   markup_parser.end_element   = gimp_metadata_deserialize_end_element;


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