java-topology/defects/squid-0002/TICKET.md
russell@unturf.com 5f0585ef76 squid: 5-MOAD scan complete; add TICKET.md for squid-0001/0002/0003, mark SCAN-TODO done
All 4 squid defects confirmed: squid-0001 CWE-407 NotePairs::appendNewOnly hasPair O(S*D)
374x; squid-0002 CWE-407 removeConnectionHeaderEntries strListIsMember O(H*C) 3x; squid-0003
CWE-312 FTP+Basic auth passwords logged verbatim incl DBG_IMPORTANT; squid-0004 CWE-407
whichPeer() O(P*A) ICP peer map 83x. MOAD-0002 SquidConfig god-object documented (structural).
MOAD-0003/0005 CLEAN. All 4 unit tests PASS.
2026-04-03 14:58:20 -04:00

1.5 KiB

squid-0002 — CWE-407 O(H*C) removeConnectionHeaderEntries() strListIsMember inner loop

Target: Squid (squid-cache/squid, depth=1, 2026-03-31) File: src/HttpHeader.cc Function: HttpHeader::removeConnectionHeaderEntries() UNDF: UNDF-2026-000001162 Severity: MEDIUM MOAD: 0001 Benchmark: 3.27x wallclock, 40x op-count at H=200 headers, C=50 Connection tokens

Defect

removeConnectionHeaderEntries() strips hop-by-hop headers listed in our Connection: header field. It calls strListIsMember() inside our getEntry() loop:

// Old comment in code: "think: on-average-best nesting of the two loops"
while ((e = getEntry(&pos))) {
    if (strListIsMember(&strConnection, e->name, ','))   // O(C) scan per header
        delAt(pos, headers_deleted);
}

strListIsMember() tokenizes our Connection string on each call, doing O(C) work per header entry. Total: O(H * C) per response hop.

Called in removeHopByHopEntries() for every forwarded HTTP response. At H=200 headers and C=50 Connection tokens: 10,000 string comparisons per response.

Fix

Pre-build an std::unordered_set<SBuf, SBufHashCmp> from Connection tokens once before our header loop (O(C) inserts), then probe O(1) per header entry. Total: O(C + H) instead of O(H * C).

Test

test/SquidConnHeaderTest.java — pure Java simulation, no Squid install needed. 3.27x wallclock speedup confirmed at H=200, C=50. Correctness verified (same 3 hop-by-hop headers removed in both paths).