# 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

```c
// 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

```c
// 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.

```c
// 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`.
