This is an automated email from the ASF dual-hosted git repository.

cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 0484c8788a60f8c0c1f231a1d2f55f1513e54d41
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.
    
    (cherry picked from commit e698e468fb2d6f9300c18fb86763177d73e49264)
---
 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 6d0cde9643..d7ba502692 100644
--- a/src/proxy/hdrs/XPACK.cc
+++ b/src/proxy/hdrs/XPACK.cc
@@ -322,7 +322,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 a7f3da0e92..bf81f3a16a 100644
--- a/src/proxy/hdrs/unit_tests/test_XPACK.cc
+++ b/src/proxy/hdrs/unit_tests/test_XPACK.cc
@@ -150,6 +150,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")
@@ -177,6 +181,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");
@@ -192,6 +199,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);
@@ -232,6 +242,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);

Reply via email to