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.
This commit is contained in:
Jacob Boerema
2022-04-04 16:52:10 -04:00
parent 6e87466b6b
commit cadf485299

View File

@ -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;
gexiv2_metadata_try_set_tag_multiple (g2_metadata,
parse_data->name,
(const gchar **) values,
&error);
if (error)
if (length > 1000 &&
! g_strcmp0 (parse_data->name, "Xmp.photoshop.DocumentAncestors"))
{
g_warning ("%s: failed to set multiple metadata '%s': %s\n",
G_STRFUNC, parse_data->name, error->message);
g_clear_error (&error);
/* 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. */
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
{
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;