java-topology/defects/binutils/patch/binutils-0001-unique-section-list.md

2 KiB
Raw Blame History

UNDF: UNDF-2026-000000354

binutils-0001 — ldlang.c unique_section_p O(S×U) linked-list scan

Severity: MEDIUM CWE: CWE-407 (Inefficient Algorithmic Complexity) File: ld/ldlang.c Functions: unique_section_p (line 389), lang_add_unique (line 10269) Repo: https://sourceware.org/git/binutils-gdb.git

Defect

unique_section_list is a singly-linked list. Two O(N) linear scans exist:

1. unique_section_p — O(U) per call, called O(S) times → O(S×U) total

// ld/ldlang.c:402
for (unam = unique_section_list; unam; unam = unam->next)
  if (name_match (unam->name, secnam) == 0)
    return true;

Called from three section-placement paths during linking:

  • output_section_callback_sort (line 776) — called per matching section
  • output_section_callback_nosort (line 3002, 3024) — called per matching section
  • orphan section placement (line 7784) — called per unplaced section

For a large binary with S=100K input sections and U=1K unique-section patterns (common in embedded/RTOS linker scripts with per-function sections), this is 100M name_match calls.

2. lang_add_unique — O(U) dedup scan on each insertion

// ld/ldlang.c:10273
for (ent = unique_section_list; ent; ent = ent->next)
  if (strcmp (ent->name, name) == 0)
    return;

Called O(U) times during linker script parsing. Each call scans the entire existing list → O(U²) total for adding U entries.

Fix

Replace unique_section_list linked list with a hash set.

// Replace:
static struct unique_sections *unique_section_list;

// With:
static htab_t unique_section_htab;  /* htab_t keyed on section name */
  • unique_section_p: htab_find → O(1) average
  • lang_add_unique: htab_find_slot → O(1) average

Complexity

Scenario Before After
S=100K sections, U=1K unique patterns O(100M) O(100K)
U=100 unique entries, insert all O(5K) dedup O(100)

Speedup at S=10K, U=500: ~500x op-count reduction for unique_section_p.