java-topology/defects/kicad-0003/SCAN-NOTES.md
russell@unturf.com 3bf7ed2cec freecad+kicad: 5-MOAD scan; 3 CWE-407 defects, MOAD 0002-0005 CLEAN
freecad-0003: CrossSection::removeDuplicates O(W^2*E) wire dedup via
std::find_if over growing list; fix: hash-keyed seen-set O(W*E log E).
Severity MEDIUM-HIGH, ~200x at W=400 duplicate wires.

freecad-0004: SketchAnalysis::detectMissingEqualityConstraints O(C*M^2)
std::find_if over std::list of equal-line/radius candidates; fix:
unordered_multimap keyed on canonical (GeoId,GeoId) pair, O(C).
Severity MEDIUM-HIGH, ~5x at C=50/M=50, grows with M^2.

kicad-0003: BOARD_NETLIST_UPDATER::testConnectivity calls FindPadByNumber
(O(P) linear scan) for each of N pins per footprint; fix: build
unordered_map<padNumber,PAD*> once per footprint, O(P+N) total.
Severity HIGH, ~19x at P=256 pads, ~512x at P=512 pads.

MOAD-0002/0003/0004/0005: CLEAN for both projects (documented in SCAN-NOTES).
2026-03-31 22:09:45 -04:00

1.8 KiB

kicad-0003 — BOARD_NETLIST_UPDATER FindPadByNumber O(N*P)

Location

pcbnew/netlist_reader/board_netlist_updater.cpp — testConnectivity()

Pattern

MOAD-0001 (CWE-407): list membership test inside loop.

for( unsigned jj = 0; jj < component->GetNetCount(); jj++ )
{
    padNumber = component->GetNet( jj ).GetPinName();
    ...
    else if( !footprint->FindPadByNumber( padNumber ) )  // O(P) each call
    ...
}

FindPadByNumber() in footprint.cpp performs a linear scan over m_pads.

Complexity

  • Outer: O(N) pins per component
  • Inner: O(P) pads per FindPadByNumber call
  • Total: O(N * P) per footprint validated

For a 512-pad BGA component: ~262,000 comparisons vs ~512 with a hash set.

Fix

Build std::unordered_map<wxString, PAD*> once per footprint (O(P)), then look up each pin in O(1). Total: O(P + N).

Severity

HIGH — called during every netlist import/validation (UpdateNetlist). Large designs (multi-BGA boards) trigger this per footprint, per import.

Secondary Instance

FOOTPRINT::Similarity() (footprint.cpp line ~4228) also calls FindPadByNumber() per pad in a loop: O(P^2) per similarity comparison. This is called by matchItemsBySimilarity<PAD> in pcb_edit_frame.cpp. A cached pad map on FOOTPRINT would fix both sites.

MOAD-0002/0003/0004/0005

  • MOAD-0002 (Intertangle): BOARD is a large god object but subsystems have defined interfaces. No new actionable instance beyond existing architecture.
  • MOAD-0003 (Leaked Context): No thread_local carrying request identity in first-party KiCad code. thread_local usage is in thirdparty only. CLEAN.
  • MOAD-0004 (CWE-312): kicad_git_common.cpp logs username (not password) in trace output. m_password is not logged. CLEAN.
  • MOAD-0005 (Thundering Herd): DRC runs single-threaded per engine invocation. No unsynchronized shared cache. CLEAN.