java-topology/defects/gimp/patch/gimp-0001-layer-stack-dedup-quadratic.patch

63 lines
2 KiB
Diff
Raw Permalink 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-000000793
# UNDF: (leave blank)
# CWE-407: Algorithmic Complexity — layer stack dedup O(S² × L²)
# File: app/core/gimpimage.c
# Severity: MEDIUM
# Ratio: 250x at S=50,L=10
#
# gimp_image_rec_remove_layer_stack_dups() removes duplicate entries from
# the layer_stack (MRU history of selected-layer sets). For each stack
# entry, it calls g_slist_find_custom() which scans remaining entries (O(S)).
# The comparison function gimp_image_layer_stack_cmp() calls g_list_length()
# on both lists (O(L) each) and then g_list_find() in a loop (O(L²)).
# Combined: O(S² × L²). Called on every layer removal.
#
# Fix: compare using sorted pointer arrays for O(L log L) comparison,
# or hash the selection sets for O(1) identity check.
--- a/app/core/gimpimage.c
+++ b/app/core/gimpimage.c
@@ -1969,18 +1969,25 @@
static gint
gimp_image_layer_stack_cmp (GList *layers1,
GList *layers2)
{
- if (g_list_length (layers1) != g_list_length (layers2))
- {
- /* We don't really need to order lists of layers, and only care
- * about identity.
- */
- return 1;
- }
- else
+ guint len1 = 0, len2 = 0;
+ GHashTable *set;
+ GList *iter;
+
+ /* Count lengths in a single pass each */
+ for (iter = layers1; iter; iter = iter->next) len1++;
+ for (iter = layers2; iter; iter = iter->next) len2++;
+ if (len1 != len2)
+ return 1;
+
+ /* Build a hash set from layers2 for O(1) membership test */
+ set = g_hash_table_new (g_direct_hash, g_direct_equal);
+ for (iter = layers2; iter; iter = iter->next)
+ g_hash_table_add (set, iter->data);
+
+ for (iter = layers1; iter; iter = iter->next)
{
- GList *iter;
-
- for (iter = layers1; iter; iter = iter->next)
+ if (! g_hash_table_contains (set, iter->data))
{
- if (! g_list_find (layers2, iter->data))
- return 1;
+ g_hash_table_destroy (set);
+ return 1;
}
- return 0;
}
+ g_hash_table_destroy (set);
+ return 0;
}