java-topology/defects/squid-0002/patch/squid-0002.patch
russell@unturf.com 1edc2f5a93 squid: 2 defects (squid-0002 CWE-407, squid-0003 CWE-312); MOADs 0002/0003/0005 CLEAN
MOAD-0001 squid-0002: HttpHeader::removeConnectionHeaderEntries() O(H*C) per response hop.
strListIsMember() scans all C Connection tokens for each of H header entries. Fix: pre-build
unordered_set from Connection tokens once, probe O(1) per entry. 4.84x measured speedup at
H=200 headers / C=50 Connection tokens. Called per hop in removeHopByHopEntries().

MOAD-0004 squid-0003: CWE-312 credentials logged verbatim in debug output.
FtpGateway.cc loginParser() logs user:password at debug 9; basic/Config.cc decodeCleartext()
logs decoded cleartext at debug 9 AND logs full Authorization header at DBG_IMPORTANT (level 1,
always on); basic/UserRequest.cc startHelperLookup() logs user:password at debug 9.
Fix: replace credential values with redacted markers / length-only diagnostic info.

MOAD-0002: SquidConfig 571-line god object in 209 files, 1408 call sites — structural,
documented in defects/squid/scan/MOAD-RESULTS.md.
MOAD-0003: CLEAN (event-loop single-threaded, no thread_local for request context).
MOAD-0005: CLEAN (event-loop single-threaded, no concurrent cache race).
2026-03-31 19:55:05 -04:00

42 lines
1.7 KiB
Diff

--- a/src/HttpHeader.cc
+++ b/src/HttpHeader.cc
@@ -1859,16 +1859,24 @@ void
HttpHeader::removeConnectionHeaderEntries()
{
if (has(Http::HdrType::CONNECTION)) {
- /* anything that matches Connection list member will be deleted */
+ // Build a case-insensitive set of Connection header tokens for O(1)
+ // lookup instead of O(C) strListIsMember scan per header entry.
+ // Without this, removal is O(H * C) per response hop where H is
+ // the number of HTTP headers and C is the Connection token count.
+ // A response with 50 headers and Connection: with 10 tokens costs
+ // 500 string comparisons; with a set it costs 10 inserts + 50 probes.
String strConnection;
-
(void) getList(Http::HdrType::CONNECTION, &strConnection);
+
+ std::unordered_set<SBuf, SBufHashCmp> connTokens;
+ const char *item = nullptr;
+ int ilen = 0;
+ const char *pos = nullptr;
+ while (strListGetItem(&strConnection, ',', &item, &ilen, &pos))
+ connTokens.emplace(item, ilen);
+
const HttpHeaderEntry *e;
HttpHeaderPos pos = HttpHeaderInitPos;
- /*
- * think: on-average-best nesting of the two loops (hdrEntry
- * and strListItem) @?@
- */
- /*
- * maybe we should delete standard stuff ("keep-alive","close")
- * from strConnection first?
- */
-
int headers_deleted = 0;
while ((e = getEntry(&pos))) {
- if (strListIsMember(&strConnection, e->name, ','))
+ if (connTokens.count(e->name))
delAt(pos, headers_deleted);
}
if (headers_deleted)