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

moonchen 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 92112e1b8a header_rewrite: Fix a leak and truncation in set-body-from 
(#13303)
92112e1b8a is described below

commit 92112e1b8ac31030c150f321e98392e7766b503f
Author: Mo Chen <[email protected]>
AuthorDate: Sat Jun 20 08:54:42 2026 -0500

    header_rewrite: Fix a leak and truncation in set-body-from (#13303)
    
    Two related fixes in the header_rewrite set-body-from operator's 
createRequestString():
    
    Memory leak. The request URL was fetched with TSUrlStringGet(), which 
returns a TSmalloc()-allocated buffer the caller owns, but it was never freed. 
Every non-internal transaction matching a set-body-from rule leaked one 
URL-sized allocation, growing unbounded over time. Free it, mirroring the 
existing owned-pointer handling in ConditionUrl.
    
    Truncation / buffer over-read. snprintf() returns the length it would have 
written, not the number of bytes actually written, and that value can exceed 
the 256-byte req_buf. Passing it to TSFetchUrl() as the request length reads 
past the stack buffer when a URL overflows. The request has always been capped 
at 256 bytes — snprintf() only ever writes that much into req_buf — so this 
changes nothing for requests that fit; it just returns TS_ERROR on overflow 
instead of over-reading. (Rai [...]
---
 plugins/header_rewrite/operators.cc | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/plugins/header_rewrite/operators.cc 
b/plugins/header_rewrite/operators.cc
index 20207bd24b..2913c9349f 100644
--- a/plugins/header_rewrite/operators.cc
+++ b/plugins/header_rewrite/operators.cc
@@ -100,12 +100,19 @@ createRequestString(const std::string_view &value, char 
(&req_buf)[MAX_SIZE], in
 
   if (TSUrlCreate(url_buf, &url_loc) == TS_SUCCESS && TSUrlParse(url_buf, 
url_loc, &start, end) == TS_PARSE_DONE) {
     const char *host = TSUrlHostGet(url_buf, url_loc, &host_len);
-    const char *url  = TSUrlStringGet(url_buf, url_loc, &url_len);
+    char       *url  = TSUrlStringGet(url_buf, url_loc, &url_len);
 
-    *req_buf_size = snprintf(req_buf, MAX_SIZE, "GET %.*s HTTP/1.1\r\nHost: 
%.*s\r\n\r\n", url_len, url, host_len, host);
+    int written = snprintf(req_buf, MAX_SIZE, "GET %.*s HTTP/1.1\r\nHost: 
%.*s\r\n\r\n", url_len, url, host_len, host);
 
+    TSfree(url);
     TSMBufferDestroy(url_buf);
 
+    if (written < 0 || static_cast<unsigned int>(written) >= MAX_SIZE) {
+      Dbg(pi_dbg_ctl, "Request string does not fit in %u byte buffer, not 
sending truncated request", MAX_SIZE);
+      return TS_ERROR;
+    }
+    *req_buf_size = written;
+
     return TS_SUCCESS;
   } else {
     Dbg(pi_dbg_ctl, "Failed to parse url %s", start);

Reply via email to