63 lines
2 KiB
Diff
63 lines
2 KiB
Diff
# 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;
|
||
}
|