From e88052e34c4efd7a8b79effcde9d51cd4e5dd6ca Mon Sep 17 00:00:00 2001 From: Serris Santos Date: Tue, 17 Mar 2026 14:17:57 -0700 Subject: [PATCH 1/3] Check valid parent selection hash string --- src/proxy/ParentSelection.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/proxy/ParentSelection.cc b/src/proxy/ParentSelection.cc index b282fba7b38..47bb01b1bbd 100644 --- a/src/proxy/ParentSelection.cc +++ b/src/proxy/ParentSelection.cc @@ -556,6 +556,11 @@ ParentRecord::ProcessParents(char *val, bool isPrimary) errPtr = "Parent string is empty"; goto MERROR; } + if (tmp3 && strlen(tmp3) > MAXDNAME) { + errPtr = "Parent hash_string is too long"; + goto MERROR; + } + // Update the pRecords if (isPrimary) { memcpy(this->parents[i].hostname, current, tmp - current); From 1ddcca1774fc9a3bb52775f8f6b9926c183aa22b Mon Sep 17 00:00:00 2001 From: Serris Santos Date: Tue, 24 Mar 2026 12:52:48 -0700 Subject: [PATCH 2/3] add regression test --- src/proxy/ParentSelection.cc | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/proxy/ParentSelection.cc b/src/proxy/ParentSelection.cc index 47bb01b1bbd..c312588d691 100644 --- a/src/proxy/ParentSelection.cc +++ b/src/proxy/ParentSelection.cc @@ -32,6 +32,7 @@ #include "tscore/Regression.h" #include "tscore/Tokenizer.h" +#include #include using namespace std::literals; @@ -557,7 +558,7 @@ ParentRecord::ProcessParents(char *val, bool isPrimary) goto MERROR; } if (tmp3 && strlen(tmp3) > MAXDNAME) { - errPtr = "Parent hash_string is too long"; + errPtr = "Parent hash string is too long"; goto MERROR; } @@ -1953,6 +1954,37 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */, FP; RE(verify(result, ParentResultType::SPECIFIED, "minnie", 80), 213); + // Test 214 + // Overlong hash_string (MAXDNAME chars) should be rejected by ProcessParents. + // The entry is discarded so findParent returns DIRECT. + { + tbl[0] = '\0'; + ST(214); + std::string long_hash(MAXDNAME, 'a'); + std::string cfg = "dest_domain=. parent=host:80&" + long_hash + " round_robin=consistent_hash go_direct=true\n"; + ink_strlcpy(tbl, cfg.c_str(), sizeof(tbl)); + REBUILD; + REINIT; + br(request, "overlong.hash.net"); + FP; + RE(verify(result, ParentResultType::DIRECT, nullptr, 0), 214); + } + + // Test 215 + // Max-length hash_string that fits (MAXDNAME-1 chars) should be accepted. + { + tbl[0] = '\0'; + ST(215); + std::string max_hash(MAXDNAME - 1, 'b'); + std::string cfg = "dest_domain=. parent=host:80&" + max_hash + " round_robin=consistent_hash go_direct=false\n"; + ink_strlcpy(tbl, cfg.c_str(), sizeof(tbl)); + REBUILD; + REINIT; + br(request, "maxlen.hash.net"); + FP; + RE(verify(result, ParentResultType::SPECIFIED, "host", 80), 215); + } + delete request; delete result; delete params; From 287ba18b1024cd7dd2dbb91a521de5e1d0cc950d Mon Sep 17 00:00:00 2001 From: Serris Santos Date: Wed, 25 Mar 2026 10:28:27 -0700 Subject: [PATCH 3/3] off by one --- src/proxy/ParentSelection.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/proxy/ParentSelection.cc b/src/proxy/ParentSelection.cc index c312588d691..a1bc20452fb 100644 --- a/src/proxy/ParentSelection.cc +++ b/src/proxy/ParentSelection.cc @@ -557,7 +557,7 @@ ParentRecord::ProcessParents(char *val, bool isPrimary) errPtr = "Parent string is empty"; goto MERROR; } - if (tmp3 && strlen(tmp3) > MAXDNAME) { + if (tmp3 && strlen(tmp3 + 1) > MAXDNAME) { errPtr = "Parent hash string is too long"; goto MERROR; } @@ -1955,12 +1955,12 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */, RE(verify(result, ParentResultType::SPECIFIED, "minnie", 80), 213); // Test 214 - // Overlong hash_string (MAXDNAME chars) should be rejected by ProcessParents. + // Overlong hash_string (exceeding MAXDNAME chars) should be rejected by ProcessParents. // The entry is discarded so findParent returns DIRECT. { tbl[0] = '\0'; ST(214); - std::string long_hash(MAXDNAME, 'a'); + std::string long_hash(MAXDNAME + 1, 'a'); std::string cfg = "dest_domain=. parent=host:80&" + long_hash + " round_robin=consistent_hash go_direct=true\n"; ink_strlcpy(tbl, cfg.c_str(), sizeof(tbl)); REBUILD; @@ -1971,11 +1971,11 @@ EXCLUSIVE_REGRESSION_TEST(PARENTSELECTION)(RegressionTest * /* t ATS_UNUSED */, } // Test 215 - // Max-length hash_string that fits (MAXDNAME-1 chars) should be accepted. + // Max-length hash_string that fits (MAXDNAME chars) should be accepted. { tbl[0] = '\0'; ST(215); - std::string max_hash(MAXDNAME - 1, 'b'); + std::string max_hash(MAXDNAME, 'b'); std::string cfg = "dest_domain=. parent=host:80&" + max_hash + " round_robin=consistent_hash go_direct=false\n"; ink_strlcpy(tbl, cfg.c_str(), sizeof(tbl)); REBUILD;