# UNDF: UNDF-2026-000000008 --- a/apps/confbridge/include/confbridge.h +++ b/apps/confbridge/include/confbridge.h @@ -258,6 +258,10 @@ struct confbridge_conference { AST_LIST_HEAD_NOLOCK(, confbridge_user) active_list; AST_LIST_HEAD_NOLOCK(, confbridge_user) waiting_list; + /* + * CWE-407 fix: O(1) user lookup by channel name. + * Maintained in sync with active_list + waiting_list. + */ + struct ao2_container *users_by_name; --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -conf_bridge_alloc,0 @@ + conference->users_by_name = ao2_container_alloc_hash( + AO2_ALLOC_OPT_LOCK_NOLOCK, 0, 127, + user_name_hash_fn, NULL, user_name_cmp_fn); /* On user join — replace list insert + O(n) search with O(1) link */ - AST_LIST_INSERT_TAIL(&conference->active_list, user, list); + AST_LIST_INSERT_TAIL(&conference->active_list, user, list); + ao2_link(conference->users_by_name, user); /* On user leave */ - AST_LIST_REMOVE(&conference->active_list, user, list); + AST_LIST_REMOVE(&conference->active_list, user, list); + ao2_unlink(conference->users_by_name, user); /* Replace every AST_LIST_TRAVERSE + strcasecmp pattern: */ - AST_LIST_TRAVERSE(&conference->active_list, user, list) { - if (strcasecmp(ast_channel_name(user->chan), - old_snapshot->base->name) == 0) { - found_user = 1; - break; - } - } - if (!found_user && conference->waitingusers) { - AST_LIST_TRAVERSE(&conference->waiting_list, user, list) { - if (strcasecmp(ast_channel_name(user->chan), - old_snapshot->base->name) == 0) { - found_user = 1; - break; - } - } - } + user = ao2_find(conference->users_by_name, + old_snapshot->base->name, OBJ_SEARCH_KEY); + found_user = (user != NULL); +static int user_name_hash_fn(const void *obj, const int flags) +{ + const struct confbridge_user *u = obj; + return flags & OBJ_SEARCH_KEY + ? ast_str_case_hash(obj) + : ast_str_case_hash(ast_channel_name(u->chan)); +} + +static int user_name_cmp_fn(void *obj, void *arg, int flags) +{ + const struct confbridge_user *u = obj; + const char *name = (flags & OBJ_SEARCH_KEY) + ? (const char *)arg + : ast_channel_name(((struct confbridge_user *)arg)->chan); + return strcasecmp(ast_channel_name(u->chan), name) ? 0 : CMP_MATCH | CMP_STOP; +}