This is an automated email from the ASF dual-hosted git repository.
bneradt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new e698e468fb Fix XPACK relative index underflow (#13144)
e698e468fb is described below
commit e698e468fb2d6f9300c18fb86763177d73e49264
Author: Brian Neradt <[email protected]>
AuthorDate: Fri May 8 15:56:56 2026 -0500
Fix XPACK relative index underflow (#13144)
XPACK dynamic table lookups convert absolute matches into HPACK
relative indexes. If an impossible future absolute index reached that
conversion path, unsigned subtraction could wrap and report a bogus
relative index.
This guards the conversion by preserving unmatched lookup results and
rejecting absolute indexes beyond the current dynamic-table head before
subtracting. This also adds XPACK unit coverage for empty, missing, and
normal relative lookup results.
---
src/proxy/hdrs/XPACK.cc | 11 ++++++++++-
src/proxy/hdrs/unit_tests/test_XPACK.cc | 19 +++++++++++++++++++
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/src/proxy/hdrs/XPACK.cc b/src/proxy/hdrs/XPACK.cc
index 388618a14d..78acdf056d 100644
--- a/src/proxy/hdrs/XPACK.cc
+++ b/src/proxy/hdrs/XPACK.cc
@@ -328,7 +328,16 @@ const XpackLookupResult
XpackDynamicTable::lookup_relative(const char *name, size_t name_len, const
char *value, size_t value_len) const
{
XpackLookupResult result = this->lookup(name, name_len, value, value_len);
- result.index = this->_entries[this->_entries_head].index -
result.index;
+ if (result.match_type == XpackLookupResult::MatchType::NONE) {
+ return result;
+ }
+
+ uint32_t const head_index = this->_entries[this->_entries_head].index;
+ if (result.index > head_index) {
+ return {0, XpackLookupResult::MatchType::NONE};
+ }
+
+ result.index = head_index - result.index;
return result;
}
diff --git a/src/proxy/hdrs/unit_tests/test_XPACK.cc
b/src/proxy/hdrs/unit_tests/test_XPACK.cc
index ee9c995089..e8133daac4 100644
--- a/src/proxy/hdrs/unit_tests/test_XPACK.cc
+++ b/src/proxy/hdrs/unit_tests/test_XPACK.cc
@@ -146,6 +146,10 @@ TEST_CASE("XPACK_String", "[xpack]")
REQUIRE(dt.count() == 0);
result = dt.lookup("", "");
REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ REQUIRE(result.index == 0);
+ result = dt.lookup_relative("", "");
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ REQUIRE(result.index == 0);
}
SECTION("Dynamic Table")
@@ -173,6 +177,9 @@ TEST_CASE("XPACK_String", "[xpack]")
REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
result = dt.lookup(MAX_SIZE + 1, &name, &name_len, &value, &value_len);
REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup_relative("missing", "value");
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ REQUIRE(result.index == 0);
// Insert one entry
dt.insert_entry("name1", "value1");
@@ -188,6 +195,9 @@ TEST_CASE("XPACK_String", "[xpack]")
REQUIRE(memcmp(value, "value1", value_len) == 0);
result = dt.lookup(dt.largest_index() + 1, &name, &name_len, &value,
&value_len);
REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup_relative("missing", "value1");
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ REQUIRE(result.index == 0);
result = dt.lookup(MAX_SIZE - 1, &name, &name_len, &value, &value_len);
REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
@@ -228,6 +238,15 @@ TEST_CASE("XPACK_String", "[xpack]")
REQUIRE(memcmp(name, "name1", name_len) == 0);
REQUIRE(value_len == strlen("value1"));
REQUIRE(memcmp(value, "value1", value_len) == 0);
+ result = dt.lookup_relative("name2", "value2");
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(result.index == 0);
+ result = dt.lookup_relative("name1", "value1");
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(result.index == 1);
+ result = dt.lookup_relative("missing", "value2");
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ REQUIRE(result.index == 0);
result = dt.lookup(MAX_SIZE - 1, &name, &name_len, &value, &value_len);
REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
result = dt.lookup(MAX_SIZE, &name, &name_len, &value, &value_len);