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).
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
FindPadByNumbercall - 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_localcarrying request identity in first-party KiCad code.thread_localusage is in thirdparty only. CLEAN. - MOAD-0004 (CWE-312):
kicad_git_common.cpplogs username (not password) in trace output.m_passwordis not logged. CLEAN. - MOAD-0005 (Thundering Herd): DRC runs single-threaded per engine invocation. No unsynchronized shared cache. CLEAN.