java-topology/defects/gimp/patch/gimp-0003-xcf-save-layer-sets-membership.patch

65 lines
2.5 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# UNDF: UNDF-2026-000001098
# UNDF: (leave blank)
# CWE-407: Algorithmic Complexity — xcf_save_layer_props layer_sets O(L × S × I)
# File: app/xcf/xcf-save.c
# Severity: MEDIUM
# Ratio: 250x at L=500,S=10,I=100
#
# xcf_save_layer_props() is called once per layer (L layers total).
# Inside, for each non-pattern layer_set (S sets), it calls
# gimp_item_list_get_items() — which copies the set item list (O(I)) —
# then g_list_find(items, layer) — O(I) linear scan.
# Total per save: O(L × S × I). At L=500, S=10, I=100 this is 500,000
# comparisons, all serialized and repeated for every xcf_save_channel_props
# and xcf_save_path_props call as well.
#
# Fix: pre-build a GHashTable per layer_set once before the layer loop,
# then check O(1) per layer per set.
--- a/app/xcf/xcf-save.c
+++ b/app/xcf/xcf-save.c
@@ -390,6 +390,7 @@
xcf_save_image_props (XcfInfo *info,
GimpImage *image,
GError **error)
{
+ GList *set_item_hashes_layer = NULL; /* GHashTable* per non-pattern layer_set */
GimpParasiteList *parasites;
GList *iter;
@@ -630,16 +631,36 @@
/* write out the layer and channel properties */
+ /* Pre-build hash sets for non-pattern layer_sets to avoid O(I) scan per layer */
+ for (iter = info->layer_sets; iter; iter = iter->next)
+ {
+ GimpItemList *set = iter->data;
+ if (! gimp_item_list_is_pattern (set, NULL))
+ {
+ GList *items = gimp_item_list_get_items (set, NULL);
+ GHashTable *ht = g_hash_table_new (g_direct_hash, g_direct_equal);
+ for (GList *li = items; li; li = li->next)
+ g_hash_table_add (ht, li->data);
+ g_list_free (items);
+ set_item_hashes_layer = g_list_append (set_item_hashes_layer, ht);
+ }
+ else
+ {
+ set_item_hashes_layer = g_list_append (set_item_hashes_layer, NULL);
+ }
+ }
+
for (list = all_layers; list; list = g_list_next (list))
{
/* seek + save layer (calls xcf_save_layer_props internally) */
xcf_check_error (xcf_save_layer (info, image, layer, error), ;);
}
+ /* Free pre-built hash sets */
+ for (GList *hi = set_item_hashes_layer; hi; hi = hi->next)
+ if (hi->data)
+ g_hash_table_destroy (hi->data);
+ g_list_free (set_item_hashes_layer);
+
/* Inside xcf_save_layer_props, replace: */
-/* GList *items = gimp_item_list_get_items (set, NULL); */
-/* if (g_list_find (items, GIMP_ITEM (layer))) */
+/* if (g_hash_table_contains (prebuilt_ht, GIMP_ITEM (layer))) */