java-topology/defects/pidgin-0001/TICKET.md

1.4 KiB

pidgin-0001 — CWE-407 add_all_buddies_to_permit_list O(B^2) GSList scan

MOAD: 0001 (CWE-407 Sedimentary Defect) Severity: MEDIUM Ratio: 499.5x at B=1000 UNDF: UNDF-2026-000001141

Location

libpurple/privacy.cadd_all_buddies_to_permit_list()

Pattern

add_all_buddies_to_permit_list() synchronizes our account permit (allow) list with our buddy list. It calls purple_find_buddies(account, NULL) to get all B buddies, then iterates them. For each buddy it calls:

g_slist_find_custom(account->permit, name, (GCompareFunc)g_utf8_collate)

account->permit is a GSList. As buddies are added our permit list grows. Each g_slist_find_custom scans our entire growing list: O(B^2/2) total.

With 1000 contacts, switching privacy modes triggers 499,500 string comparisons instead of 1,000.

Called from purple_privacy_allow() and purple_privacy_deny() when switching from ALLOW_BUDDYLIST mode.

Fix

Before our buddy iteration loop, snapshot account->permit into a GHashTable for O(1) membership tests. Replace g_slist_find_custom() with g_hash_table_lookup(). Destroy our snapshot after our loop.

Speedup

B (buddies) Defective ops Fixed ops Ratio
100 4,950 100 49.5x
500 124,750 500 249.5x
1,000 499,500 1,000 499.5x
2,000 1,999,000 2,000 999.5x