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


The following commit(s) were added to refs/heads/10.1.x by this push:
     new e55545540b Fix set-status crash inside if/endif at remap time (#13366)
e55545540b is described below

commit e55545540bb741efcfe1027da4df3e17c02683ab
Author: Mo Chen <[email protected]>
AuthorDate: Mon Jul 13 09:44:21 2026 -0500

    Fix set-status crash inside if/endif at remap time (#13366)
    
    Operators inside an if/endif block never had set_hook() called on them,
    so _hook retained its default value of TS_HTTP_READ_RESPONSE_HDR_HOOK.
    When set-status executed at REMAP_PSEUDO_HOOK time, exec() took the
    response-hook branch and called TSHttpHdrStatusSet on a request buffer,
    corrupting the header union and crashing.
    
    Fix the operator to check TSHttpHdrTypeGet() at runtime instead of
    trusting get_hook().  Removed _hook and get_hook() from operators.
    
    set_hook() becomes is_hook_valid() in Statement and RuleSet to
    only validate hook compatibility without mutating _hook.
    
    Upgrade the HTTPHdr::status_set/reason_set asserts to release_assert so
    that writing response fields into a request buffer is caught immediately
    rather than silently corrupting memory.
    
    (cherry picked from commit e4728cc49625cc3767f77b1ecd8ad0ebdf17d016)
---
 include/proxy/hdrs/HTTP.h           |  4 ++--
 plugins/header_rewrite/operators.cc | 18 ++++++------------
 plugins/header_rewrite/ruleset.cc   |  4 ++--
 plugins/header_rewrite/statement.cc | 10 ++--------
 plugins/header_rewrite/statement.h  | 10 ++--------
 src/proxy/hdrs/HTTP.cc              |  4 ++--
 6 files changed, 16 insertions(+), 34 deletions(-)

diff --git a/include/proxy/hdrs/HTTP.h b/include/proxy/hdrs/HTTP.h
index 22d6c45a7b..22195e6366 100644
--- a/include/proxy/hdrs/HTTP.h
+++ b/include/proxy/hdrs/HTTP.h
@@ -1091,7 +1091,7 @@ inline void
 HTTPHdr::status_set(HTTPStatus status)
 {
   ink_assert(valid());
-  ink_assert(m_http->m_polarity == HTTP_TYPE_RESPONSE);
+  ink_release_assert(m_http->m_polarity == HTTP_TYPE_RESPONSE);
 
   http_hdr_status_set(m_http, status);
 }
@@ -1115,7 +1115,7 @@ inline void
 HTTPHdr::reason_set(const char *value, int length)
 {
   ink_assert(valid());
-  ink_assert(m_http->m_polarity == HTTP_TYPE_RESPONSE);
+  ink_release_assert(m_http->m_polarity == HTTP_TYPE_RESPONSE);
 
   http_hdr_reason_set(m_heap, m_http, value, length, true);
 }
diff --git a/plugins/header_rewrite/operators.cc 
b/plugins/header_rewrite/operators.cc
index 0b6b30375b..f572ae7f5c 100644
--- a/plugins/header_rewrite/operators.cc
+++ b/plugins/header_rewrite/operators.cc
@@ -202,19 +202,13 @@ OperatorSetStatus::initialize_hooks()
 bool
 OperatorSetStatus::exec(const Resources &res) const
 {
-  switch (get_hook()) {
-  case TS_HTTP_READ_RESPONSE_HDR_HOOK:
-  case TS_HTTP_SEND_RESPONSE_HDR_HOOK:
-    if (res.bufp && res.hdr_loc) {
-      TSHttpHdrStatusSet(res.bufp, res.hdr_loc, 
static_cast<TSHttpStatus>(_status.get_int_value()));
-      if (_reason && _reason_len > 0) {
-        TSHttpHdrReasonSet(res.bufp, res.hdr_loc, _reason, _reason_len);
-      }
+  if (res.bufp && res.hdr_loc && TSHttpHdrTypeGet(res.bufp, res.hdr_loc) == 
TS_HTTP_TYPE_RESPONSE) {
+    TSHttpHdrStatusSet(res.bufp, res.hdr_loc, 
static_cast<TSHttpStatus>(_status.get_int_value()));
+    if (_reason && _reason_len > 0) {
+      TSHttpHdrReasonSet(res.bufp, res.hdr_loc, _reason, _reason_len);
     }
-    break;
-  default:
+  } else {
     TSHttpTxnStatusSet(res.state.txnp, 
static_cast<TSHttpStatus>(_status.get_int_value()));
-    break;
   }
 
   Dbg(pi_dbg_ctl, "OperatorSetStatus::exec() invoked with status=%d", 
_status.get_int_value());
@@ -602,7 +596,7 @@ OperatorSetRedirect::exec(const Resources &res) const
       const_cast<Resources &>(res).changed_url = true;
       res._rri->redirect                       = 1;
     } else {
-      Dbg(pi_dbg_ctl, "OperatorSetRedirect::exec() hook=%d", int(get_hook()));
+      Dbg(pi_dbg_ctl, "OperatorSetRedirect::exec() redirect to %s", 
value.c_str());
       // Set the new status code and reason.
       TSHttpStatus status = static_cast<TSHttpStatus>(_status.get_int_value());
       TSHttpHdrStatusSet(res.bufp, res.hdr_loc, status);
diff --git a/plugins/header_rewrite/ruleset.cc 
b/plugins/header_rewrite/ruleset.cc
index 501315e063..c301522382 100644
--- a/plugins/header_rewrite/ruleset.cc
+++ b/plugins/header_rewrite/ruleset.cc
@@ -53,7 +53,7 @@ RuleSet::make_condition(Parser &p, const char *filename, int 
lineno)
   Dbg(pi_dbg_ctl, "    Creating condition: %%{%s} with arg: %s", 
p.get_op().c_str(), p.get_arg().c_str());
   c->set_config_location(filename, lineno);
   c->initialize(p);
-  if (!c->set_hook(_hook)) {
+  if (!c->is_hook_valid(_hook)) {
     delete c;
     TSError("[%s] in %s:%d: can't use this condition in hook=%s: %%{%s} with 
arg: %s", PLUGIN_NAME, filename, lineno,
             TSHttpHookNameLookup(_hook), p.get_op().c_str(), 
p.get_arg().c_str());
@@ -82,7 +82,7 @@ RuleSet::add_operator(Parser &p, const char *filename, int 
lineno)
     Dbg(pi_dbg_ctl, "    Adding operator: %s(%s)=\"%s\"", p.get_op().c_str(), 
p.get_arg().c_str(), p.get_value().c_str());
     op->set_config_location(filename, lineno);
     op->initialize(p);
-    if (!op->set_hook(_hook)) {
+    if (!op->is_hook_valid(_hook)) {
       delete op;
       Dbg(pi_dbg_ctl, "in %s:%d: can't use this operator in hook=%s:  %s(%s)", 
filename, lineno, TSHttpHookNameLookup(_hook),
           p.get_op().c_str(), p.get_arg().c_str());
diff --git a/plugins/header_rewrite/statement.cc 
b/plugins/header_rewrite/statement.cc
index ca840d7a9b..f4335e243e 100644
--- a/plugins/header_rewrite/statement.cc
+++ b/plugins/header_rewrite/statement.cc
@@ -48,15 +48,9 @@ Statement::get_resource_ids() const
 }
 
 bool
-Statement::set_hook(TSHttpHookID hook)
+Statement::is_hook_valid(TSHttpHookID hook) const
 {
-  bool ret = std::find(_allowed_hooks.begin(), _allowed_hooks.end(), hook) != 
_allowed_hooks.end();
-
-  if (ret) {
-    _hook = hook;
-  }
-
-  return ret;
+  return std::find(_allowed_hooks.begin(), _allowed_hooks.end(), hook) != 
_allowed_hooks.end();
 }
 
 // This should be overridden for any Statement which only supports some hooks
diff --git a/plugins/header_rewrite/statement.h 
b/plugins/header_rewrite/statement.h
index 510957837a..724017beb5 100644
--- a/plugins/header_rewrite/statement.h
+++ b/plugins/header_rewrite/statement.h
@@ -143,13 +143,8 @@ public:
   Statement(const Statement &)      = delete;
   void operator=(const Statement &) = delete;
 
-  // Which hook are we adding this statement to?
-  bool set_hook(TSHttpHookID hook);
-  TSHttpHookID
-  get_hook() const
-  {
-    return _hook;
-  }
+  // Validate that this statement is allowed on the given hook. Used during 
parsing only.
+  bool is_hook_valid(TSHttpHookID hook) const;
 
   // Which hooks are this "statement" applicable for? Used during parsing only.
   void
@@ -244,7 +239,6 @@ protected:
 
 private:
   ResourceIDs               _rsrc = RSRC_NONE;
-  TSHttpHookID              _hook = TS_HTTP_READ_RESPONSE_HDR_HOOK;
   std::vector<TSHttpHookID> _allowed_hooks;
   std::string               _config_filename;
   int                       _config_lineno = 0;
diff --git a/src/proxy/hdrs/HTTP.cc b/src/proxy/hdrs/HTTP.cc
index a4d350ee9e..e3fc63d763 100644
--- a/src/proxy/hdrs/HTTP.cc
+++ b/src/proxy/hdrs/HTTP.cc
@@ -754,7 +754,7 @@ http_hdr_url_set(HdrHeap *heap, HTTPHdrImpl *hh, URLImpl 
*url)
 void
 http_hdr_status_set(HTTPHdrImpl *hh, HTTPStatus status)
 {
-  ink_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
+  ink_release_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
   hh->u.resp.m_status = status;
 }
 
@@ -775,7 +775,7 @@ http_hdr_reason_get(HTTPHdrImpl *hh, int *length)
 void
 http_hdr_reason_set(HdrHeap *heap, HTTPHdrImpl *hh, const char *value, int 
length, bool must_copy)
 {
-  ink_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
+  ink_release_assert(hh->m_polarity == HTTP_TYPE_RESPONSE);
   mime_str_u16_set(heap, value, length, &(hh->u.resp.m_ptr_reason), 
&(hh->u.resp.m_len_reason), must_copy);
 }
 

Reply via email to