java-topology/whitepaper/outreach/katago.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.8 KiB
Raw Blame History

KataGo — CWE-407 Disclosure Brief (katago-0001)

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

Finding

One O(Nk) defect in KataGo's liberty counting. The Board::findLiberties() method uses a linear scan over a buffer for duplicate liberty detection, producing O(Nk) total cost where N = chain size and k = accumulated liberties. Called 25,000+ times per ladder search.

The Defect

katago-0001 (PATCHED — HIGH): cpp/game/board.cpp:1437

int Board::findLiberties(Loc loc, vector<Loc>& buf, int bufStart, int bufIdx) const {
    // For each stone in chain:
    for(int i = 0; i < 4; i++) {
        Loc lib = cur + adj_offsets[i];
        if(colors[lib] == C_EMPTY) {
            // Check for dups — O(k) linear scan
            bool foundDup = false;
            for(int j = bufStart; j < bufIdx+numFound; j++) {
                if(buf[j] == lib) { foundDup = true; break; }
            }
        }
    }
}

For each stone in a chain of size N, each adjacent liberty candidate triggers a linear scan of all previously found liberties (up to k). Total cost: O(N*k) where k grows to O(N) for scattered groups.

Complexity Proof

At chain=100 scattered stones:

  • Defective: 100 stones × ~50 avg liberties = 5,000 comparisons per call × 25,000 calls/search = 125M comparisons
  • Fixed: 100 stones × O(1) bitset lookup = 100 per call × 25,000 = 2.5M operations
  • ~50× op reduction per call. At 25,000 calls per ladder search, total savings compound.

Impact

KataGo is the strongest open-source Go engine, used by professional Go players, researchers, and online Go servers worldwide. Liberty counting fires thousands of times per move during ladder reading and life-and-death analysis. The quadratic cost compounds in deep tactical searches.

The Fix

Replace the linear dup scan with a stack-allocated bool seen[MAX_ARR_SIZE] bitset indexed by board coordinate:

// After — O(1) bitset lookup per candidate liberty
bool seen[MAX_ARR_SIZE] = {};
for(int j = bufStart; j < bufIdx; j++) seen[buf[j]] = true;
// ... in loop:
if(colors[lib] == C_EMPTY && !seen[lib]) {
    buf[bufIdx+numFound] = lib;
    seen[lib] = true;
    numFound++;
}

Patch

Fix available: defects/katago/patch/katago-0001-findliberties-bitset.patch

Single-file patch in cpp/game/board.cpp. Stack-allocated bitset (<=931 bytes). ~50× speedup per findLiberties call at chain=100.

What We Ask

A patch is ready for review.

  1. Confirm receipt and assign a GitHub issue reference (lightvector/KataGo).
  2. Assess severity — fires 25,000+ times per ladder search, quadratic in chain size.
  3. Coordinate a disclosure date — we are targeting 90 days from first contact.
  4. We will credit the KataGo team in the public disclosure. Preferred acknowledgment format welcome.

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