java-topology/whitepaper/outreach/go-libp2p-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.5 KiB
Raw Blame History

go-libp2p — CWE-407 Disclosure Brief (go-libp2p-0001)

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

Finding

One O(n²) defect in go-libp2p's protocol diffing. The diff() function in p2p/protocol/identify/id.go uses slices.Contains() for set difference computation, causing O(A*B) total cost where A and B are the old and new protocol lists.

The Defect

go-libp2p-0001 (PATCHED — MEDIUM): p2p/protocol/identify/id.go:698

// diff takes two slices and computes added/removed — commented "O(n^2), but it's fine"
func diff(a, b []protocol.ID) (added, removed []protocol.ID) {
    for _, x := range b {
        if slices.Contains(a, x) {
            found = true
        }
        // ...
    }

The existing code even acknowledges the quadratic cost with the comment "This is O(n^2), but it's fine because the slices are small." However, protocol lists grow with the number of supported protocols, and this fires on every identify exchange.

Complexity Proof

At A=50, B=50 protocols:

  • Defective: 50 × 50 + 50 × 50 = 5,000 comparisons
  • Fixed: 50 + 50 map builds + 50 + 50 lookups = 200 operations
  • ~25× op reduction.

Impact

go-libp2p is the networking stack for IPFS, Filecoin, Ethereum consensus clients, and hundreds of other decentralized applications. The identify protocol fires on every new peer connection. In a network with thousands of peers and dozens of protocols, this defect adds unnecessary CPU cost to every connection establishment.

The Fix

Build map[protocol.ID]struct{} sets from both slices, then use map lookups for O(1) membership:

// After
aSet := make(map[protocol.ID]struct{}, len(a))
for _, x := range a { aSet[x] = struct{}{} }
bSet := make(map[protocol.ID]struct{}, len(b))
for _, x := range b {
    bSet[x] = struct{}{}
    if _, ok := aSet[x]; !ok { added = append(added, x) }
}
for _, x := range a {
    if _, ok := bSet[x]; !ok { removed = append(removed, x) }
}

Patch

Fix available: defects/go-libp2p-0001/patch/go-libp2p-0001.patch

Single-file patch in p2p/protocol/identify/id.go. ~25× speedup at 50 protocols.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (libp2p/go-libp2p).
  2. Assess severity — fires on every peer identify exchange.
  3. Coordinate a disclosure date — we are targeting 90 days from first contact.
  4. We will credit the libp2p team in the public disclosure. Preferred acknowledgment format welcome.

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