# BIRD Routing Daemon — CWE-407 Disclosure Brief
**2026-03-27 · Patch available — awaiting upstream merge**

## Finding

Two O(n²) defects in BIRD's OSPF SPF priority queue and BGP community lookup. Both patched. Patches ready for upstream review. BIRD is the routing daemon used on IXP (Internet Exchange Point) route servers globally — it processes BGP routes from hundreds of peers simultaneously.

## The Defects

**bird-0001 (PATCHED — HIGH):** `proto/ospf/rt.c:1980`

```c
/* In ospf_rt_spf() — OSPF Dijkstra SPF computation:
 * WALK_LIST implements insertion sort into the candidate priority queue.
 * Each vertex insertion scans the entire candidate list for insertion position.
 * O(E × V) total — BIRD ships lib/heap.h unused here. */
WALK_LIST(en, cand) {
    if (en->metric > d->metric) break;  /* O(V) scan per vertex addition */
}
insert_node(&d->cn, en);
```

The SPF candidate priority queue is implemented as a sorted linked list with insertion sort. Each vertex added to the candidate set requires walking the entire list to find its insertion position. O(V) per insertion, O(E × V) total for E edges and V vertices. The correct data structure — a binary heap — is already implemented in `lib/heap.h` and used correctly elsewhere in BIRD, but not applied here.

**bird-0002 (PATCHED — HIGH):** `nest/a-set.c:190`

```c
/* In int_set_contains() — BGP community attribute lookup:
 * Called on every BGP route with community attributes during policy evaluation. */
int int_set_contains(const struct adata *list, u32 val) {
    const u32 *l = (const u32 *) list->data;
    int len = int_set_size(list);
    for (int i = 0; i < len; i++)
        if (l[i] == val) return 1;    /* O(C) per call */
    return 0;
}
```

`int_set_contains` is a linear scan over the BGP community list. At internet-scale route servers processing hundreds of thousands of routes with community attributes, this function is called 100M+ times per BGP convergence event.

## Complexity Proof

**bird-0001:** For V vertices and E edges in an OSPF topology:
- SPF candidate queue: insertion sort, O(V) per vertex insertion
- Total: **O(E × V)**

At V=500 routers (large enterprise flat OSPF area): defective=~125,000 comparisons per SPF run, fixed=~500 × log(500) ≈ 4,500 (heap). **~28× op reduction per SPF run.**

Every OSPF topology change (link up/down, metric change, neighbor state transition) triggers a full SPF run. During convergence storms, this runs dozens of times in quick succession.

**bird-0002:** For C communities per route and N routes:
- Per route per policy match: O(C) linear scan
- Total: **O(N × C)** per convergence

At internet scale (N=900,000 routes, C=10 communities, 100 policy matches): 100M+ linear scans per convergence. Fix: sorted array with `bsearch()` or hash set, O(log C) or O(1) per lookup.

## Impact

BIRD is the standard routing daemon for Internet Exchange Points — IXPs are the physical interconnection facilities where ISPs exchange traffic. Major IXPs (AMS-IX, DE-CIX, LINX, NYIIX) run BIRD on their route servers. BIRD route servers process BGP sessions from hundreds of member networks simultaneously.

bird-0001: OSPF is used for BIRD's own infrastructure connectivity and in network operator deployments. Every OSPF topology change triggers an SPF run; during link failures and convergence events, O(V²) SPF computation delays recovery. For large flat OSPF areas (500 routers), the delay is measurable and affects the time networks remain unreachable after a failure.

bird-0002: BGP community lookup is in the hot path of every BGP route policy evaluation. At IXP scale processing 100M+ community lookups per convergence event, the linear scan is a significant contributor to convergence time. Hash-based or sorted lookups would reduce this proportionally.

## The Fix

**bird-0001:** Use `lib/heap.h` for the SPF candidate priority queue:

```c
/* Before — insertion sort O(V) per vertex */
WALK_LIST(en, cand) {
    if (en->metric > d->metric) break;
}
insert_node(&d->cn, en);

/* After */
/* CWE-407 fix: binary heap for O(log V) insert instead of O(V) insertion sort.
 * BIRD's lib/heap.h implements a binary heap — already used in other BIRD protocols. */
HEAP_INSERT(cand_heap, d, ort_heap_compare);
```

**bird-0002:** Sort communities at announcement time, use `bsearch()` for lookup:

```c
/* Before */
for (int i = 0; i < len; i++)
    if (l[i] == val) return 1;    /* O(C) linear scan */

/* After */
/* CWE-407 fix: bsearch on sorted community list for O(log C) instead of O(C) scan.
 * Communities are sorted at announcement time; bsearch exploits sort order. */
return bsearch(&val, l, len, sizeof(u32), u32_cmp) != NULL;
```

## Patch

Fix available: `defects/bird/patch/bird-0001-0002-ospf-heap-community-bsearch.patch`

Two-location patch across `proto/ospf/rt.c` and `nest/a-set.c`.

Unit test: bird-0001 O(V×E) → O(E log V) growth confirmed on OSPF topology simulation. bird-0002: O(C) → O(log C) per lookup.

## What We Ask

A patch is ready for review.

1. Confirm receipt and assign a GitLab issue reference (gitlab.nic.cz/labs/bird) or mailing list reference.
2. Assess severity — bird-0001 affects OSPF convergence time under failure conditions; bird-0002 affects BGP convergence at IXP scale.
3. Coordinate a disclosure date — we are targeting 90 days from first contact.
4. We will credit the BIRD team in the public disclosure. Preferred acknowledgment format welcome.

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