java-topology/whitepaper/outreach/pidgin-0001.md
russell@unturf.com 652608142a feat: close outreach doc gap — 276 docs (batches 11-16)
All projects with patches now have outreach docs. 276 new docs covering
CWE-407, CWE-312, CWE-362 across C, C++, Java, Python, Go, Rust, C#,
PHP, Ruby, JavaScript, Dart, Erlang, R, and more.

Outreach gap: 276 -> 0.
2026-04-15 13:57:42 -04:00

2.4 KiB
Raw Blame History

Pidgin — CWE-407 Disclosure Brief (pidgin-0001)

2026-04-13 · Patch available — awaiting upstream merge

Finding

O(B×P) membership test in add_all_buddies_to_permit_list() where g_slist_find_custom() scans the permit list for every buddy in the account, using g_utf8_collate for comparison.

The Defect

pidgin-0001 (PATCHED — MEDIUM): libpurple/privacy.c:231

// Inside buddy iteration loop — O(P) per buddy:
if (!g_slist_find_custom(account->permit, name, (GCompareFunc)g_utf8_collate))
    purple_privacy_permit_add(account, name, local);

g_slist_find_custom traverses the entire account->permit GSList for every buddy. With B buddies and P existing permit entries, total cost is O(B×P). g_utf8_collate adds per-comparison overhead beyond simple string equality.

Complexity Proof

At B=1,000 buddies and P=500 permit entries:

  • Defective: 1,000 × 500 = 500,000 UTF-8 collation comparisons
  • Fixed: 500 hash insertions + 1,000 hash lookups = 1,500 operations
  • ~333× op reduction.

Impact

Pidgin manages buddy lists across multiple IM protocols. Privacy mode changes trigger add_all_buddies_to_permit_list(), which synchronizes the permit list with the full buddy list. Accounts with large buddy lists (common on IRC, XMPP conferences) experience visible delays during privacy mode toggling.

The Fix

Build a GHashTable permit set before the buddy iteration loop:

// Before
if (!g_slist_find_custom(account->permit, name, (GCompareFunc)g_utf8_collate))

// After
GHashTable *permit_set = g_hash_table_new(g_str_hash, g_str_equal);
for (permit_iter = account->permit; permit_iter != NULL; permit_iter = permit_iter->next)
    g_hash_table_add(permit_set, permit_iter->data);
// ...
if (!g_hash_table_lookup(permit_set, name))
    purple_privacy_permit_add(account, name, local);
// ...
g_hash_table_destroy(permit_set);

Patch

Fix available: defects/pidgin-0001/patch/pidgin-0001-permit-list-hashset.patch

Single-file patch in privacy.c.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a tracking reference (pidgin/pidgin).
  2. Assess severity — fires on privacy mode changes, scales with buddy count.
  3. Coordinate a disclosure date — we target 90 days from first contact.
  4. We will credit the Pidgin team in the public disclosure. Preferred acknowledgment format welcome.

Contact: see cover email. This brief is confidential until coordinated disclosure.