# 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; }