kubo: CLEAN across all 5 MOADs (520 Go files, hash-based data structures throughout)

This commit is contained in:
russell@unturf.com 2026-03-31 13:07:14 -04:00
parent bcdca9cb0e
commit 912baaac72
3 changed files with 191 additions and 0 deletions

View file

@ -0,0 +1,34 @@
--- a/p2p/protocol/identify/id.go
+++ b/p2p/protocol/identify/id.go
@@ -698,22 +698,18 @@ func (ids *idService) getRecordBytes() []byte {
// diff takes two slices of strings (a and b) and computes which elements were added and removed in b
func diff(a, b []protocol.ID) (added, removed []protocol.ID) {
- // This is O(n^2), but it's fine because the slices are small.
- for _, x := range b {
- var found bool
- if slices.Contains(a, x) {
- found = true
- }
- if !found {
+ 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 {
- var found bool
- if slices.Contains(b, x) {
- found = true
- }
- if !found {
+ if _, ok := bSet[x]; !ok {
removed = append(removed, x)
}
}

View file

@ -0,0 +1,128 @@
#!/usr/bin/env python3
"""
Unit test for go-libp2p-0001: identify protocol diff() uses
slices.Contains inside loop = O(N^2) protocol comparison.
Fix: use map[protocol.ID]struct{} for O(1) lookups = O(N) total.
File: p2p/protocol/identify/id.go
Function: diff(a, b []protocol.ID) (added, removed []protocol.ID)
"""
import time
import unittest
# --- DEFECTIVE VERSION: O(N^2) ---
def diff_defective(a, b):
"""Original: slices.Contains(a, x) inside for-range b loop."""
added = []
removed = []
for x in b:
if x not in a: # linear scan = O(N) per element
added.append(x)
for x in a:
if x not in b: # linear scan = O(N) per element
removed.append(x)
return added, removed
# --- PATCHED VERSION: O(N) ---
def diff_patched(a, b):
"""Patched: build sets for O(1) lookups."""
a_set = set(a)
b_set = set(b)
added = [x for x in b if x not in a_set]
removed = [x for x in a if x not in b_set]
return added, removed
class TestDiffCorrectness(unittest.TestCase):
"""Verify patched version matches defective version output."""
def _check(self, a, b, want_add, want_rem):
add_d, rem_d = diff_defective(a, b)
add_p, rem_p = diff_patched(a, b)
self.assertEqual(add_d, add_p, "added mismatch between versions")
self.assertEqual(rem_d, rem_p, "removed mismatch between versions")
self.assertEqual(add_p, want_add)
self.assertEqual(rem_p, want_rem)
def test_no_change(self):
self._check(
["/ipfs/id/1.0.0", "/ipfs/ping/1.0.0"],
["/ipfs/id/1.0.0", "/ipfs/ping/1.0.0"],
[], []
)
def test_one_added(self):
self._check(
["/ipfs/id/1.0.0"],
["/ipfs/id/1.0.0", "/ipfs/ping/1.0.0"],
["/ipfs/ping/1.0.0"], []
)
def test_one_removed(self):
self._check(
["/ipfs/id/1.0.0", "/ipfs/ping/1.0.0"],
["/ipfs/id/1.0.0"],
[], ["/ipfs/ping/1.0.0"]
)
def test_both_added_and_removed(self):
self._check(
["/proto/a", "/proto/b"],
["/proto/b", "/proto/c"],
["/proto/c"], ["/proto/a"]
)
def test_empty_to_many(self):
self._check(
[],
["/p/1", "/p/2", "/p/3"],
["/p/1", "/p/2", "/p/3"], []
)
def test_many_to_empty(self):
self._check(
["/p/1", "/p/2", "/p/3"],
[],
[], ["/p/1", "/p/2", "/p/3"]
)
class TestDiffPerformance(unittest.TestCase):
"""Benchmark: patched should be significantly faster at scale."""
def test_performance_scaling(self):
sizes = [10, 100, 500, 1000]
for n in sizes:
# Build two protocol lists with ~50% overlap
a = [f"/proto/{i}" for i in range(n)]
b = [f"/proto/{i}" for i in range(n // 2, n + n // 2)]
iters = 200
# Benchmark defective (list-based O(N^2))
start = time.perf_counter()
for _ in range(iters):
diff_defective(a, b)
defective_time = time.perf_counter() - start
# Benchmark patched (set-based O(N))
start = time.perf_counter()
for _ in range(iters):
diff_patched(a, b)
patched_time = time.perf_counter() - start
ratio = defective_time / patched_time if patched_time > 0 else float('inf')
print(f" N={n:4d} defective={defective_time:.4f}s patched={patched_time:.4f}s ratio={ratio:.1f}x")
if n >= 100:
self.assertGreater(ratio, 2.0,
f"N={n}: expected patched to be at least 2x faster, got {ratio:.1f}x")
if __name__ == "__main__":
unittest.main()

29
defects/kubo/CLEAN Normal file
View file

@ -0,0 +1,29 @@
kubo (Go IPFS implementation) — CLEAN across all 5 MOADs
Scanned: 2026-03-31
Source: ~/git/kubo (depth=1 clone from https://github.com/ipfs/kubo)
Files: 520 Go source files
MOAD-0001 (CWE-407): CLEAN
- cid.Set (hash-based) used for GC mark set, pin dedup, refs visited
- map[string]struct{} used for bootstrap dedup, address filter dedup, announce dedup
- map[string]int used for refs seen tracking
- slices.Contains only on fixed-size config lists (5 method names, 4 container inits)
- Nested loop in filtersRemove (swarm.go) is one-shot CLI config command, trivially small N
MOAD-0002 (Intertangle): No patchable defect
- IpfsNode is a large god object (30+ fields) but architectural, uses fx DI
MOAD-0003 (Leaked Context): CLEAN
- No context.WithValue abuse found
- Uses fx dependency injection for component wiring
MOAD-0004 (Logged Secret): CLEAN
- Swarm key fingerprint (hash) logged, not key itself
- API keys passed but never logged
- HTTPHeaders logged contain only CORS config
MOAD-0005 (Thundering Herd): CLEAN
- sync.Once for autoconf client singleton
- fx dependency injection for initialization
- No unsynchronized cache patterns