2.7 KiB
squid-0004 — CWE-407 O(P*A) whichPeer() linear scan on hot ICP/HTCP reply path
Target: Squid (squid-cache/squid, depth=1, 2026-04-03)
File: src/neighbors.cc
Function: whichPeer(const Ip::Address &from)
Severity: MEDIUM-HIGH
MOAD: 0001
Benchmark: 47x op-count reduction at P=100 peers, A=4 addresses/peer
Defect
whichPeer() is called on every incoming ICP and HTCP response from cache peers,
mapping a source UDP address back to a CachePeer*. It does so by scanning all
configured peers and all their addresses with a nested loop:
// src/neighbors.cc:99-114
CachePeer *
whichPeer(const Ip::Address &from)
{
int j;
for (const auto &p: CurrentCachePeers()) { // O(P)
for (j = 0; j < p->n_addresses; ++j) { // O(A)
if (from == p->addresses[j] && from.port() == p->icp.port) {
return p.get();
}
}
}
return nullptr;
}
With P=100 cache peers and A=4 addresses/peer, each call scans up to 400 entries. At 10,000 ICP responses/second (a busy CDN proxy), this is 4,000,000 scalar comparisons/second in a single function that returns on first match.
The fix builds a std::map<std::pair<Ip::Address, unsigned short>, CachePeer*>
keyed by (addr, icp_port) at peer DNS resolution time (peerDNSConfigure),
updated on address change, and cleared on peer removal. Lookup becomes O(log P)
instead of O(P*A).
Call sites:
neighborsUdpAck()— called for every incoming ICP reply packetneighborsHtcpReply()— called for every incoming HTCP reply packetpeer_select.cc— called during miss peer selection (3 sites)
Fix
Build a map (Ip::Address, icp_port) -> CachePeer* populated in peerDNSConfigure()
when peer addresses are resolved. Clear entries when a peer is removed
(DeleteConfigured). Consult the map in whichPeer() instead of scanning.
Ip::Address already supports operator< (used in ssl/context_storage.cc as
std::map<Ip::Address, ...>), so it is suitable as a map key.
MOAD 0002-0005 Scan Results
MOAD-0002 (Intertangle): SquidConfig is a 571-line god object included in
209 source files coupling every subsystem (ACL, auth, TLS, cache, DNS, ICAP, FTP).
Config.* referenced 1408 times. Documented in squid/scan/MOAD-RESULTS.md.
Structural, not patchable in isolation.
MOAD-0003 (Leaked Context): CLEAN. Squid is single-threaded event-loop per
worker process. No thread_local or pthread_key holding request-scoped identity
found.
MOAD-0004 (Logged Secret): Already patched in squid-0003. FtpGateway loginParser and auth/basic credential logging at debug level 9 addressed.
MOAD-0005 (Thundering Herd): CLEAN. Single-threaded event-loop worker model; no concurrent cache get+set race conditions applicable.