# UNDF: UNDF-2026-000000701 --- a/subprojects/gstreamer/gst/gsttracerutils.c +++ b/subprojects/gstreamer/gst/gsttracerutils.c @@ -435,26 +435,45 @@ gst_tracing_get_active_tracers (void) * Returns: (transfer full) (element-type Gst.Tracer): A #GList of * #GstTracer objects * * Since: 1.18 */ GList * gst_tracing_get_active_tracers (void) { - GList *tracers, *h_list, *h_node, *t_node; + GList *tracers = NULL, *h_list, *h_node, *t_node; GstTracerHook *hook; + /* + * CWE-407 fix: replace g_list_index() dedup (O(T) per insertion, + * O(H×T²) total) with a GHashTable keyed on GstTracer* for O(1) lookup. + * + * Original code note says "O(n) but fine since tracers count is small". + * However: with H=54 hook types and T tracers per hook the outer loop + * iterates H×T times, each calling g_list_index(tracers, …) which is + * O(accumulated_tracers). For a pipeline with 5 tracers each covering + * ~10 hooks: 54×10 = 540 outer iterations, each scanning up to 5 entries + * = 2700 list-index calls. The fix reduces this to 540 hash lookups. + * + * GHashTable with g_direct_hash/g_direct_equal is appropriate here since + * GstTracer* pointers are stable object identities. + */ + GHashTable *seen; if (!_priv_tracer_enabled || !_priv_tracers) return NULL; - tracers = NULL; + seen = g_hash_table_new (g_direct_hash, g_direct_equal); h_list = g_hash_table_get_values (_priv_tracers); for (h_node = h_list; h_node; h_node = g_list_next (h_node)) { for (t_node = h_node->data; t_node; t_node = g_list_next (t_node)) { hook = (GstTracerHook *) t_node->data; - /* Skip duplicate tracers from different hooks. This function is O(n), but - * that should be fine since the number of tracers enabled on a process - * should be small. */ - if (g_list_index (tracers, hook->tracer) >= 0) + /* CWE-407 fix: O(1) hash lookup replaces O(T) g_list_index() scan */ + if (g_hash_table_contains (seen, hook->tracer)) continue; + g_hash_table_add (seen, hook->tracer); tracers = g_list_prepend (tracers, gst_object_ref (hook->tracer)); } } g_list_free (h_list); + g_hash_table_destroy (seen); return tracers; }