This is an automated email from the ASF dual-hosted git repository. cmcfarlen pushed a commit to branch 10.2.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit e8fe4526bb7077426908c96cf6417aed6953b89d 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 [...] (cherry picked from commit 92112e1b8ac31030c150f321e98392e7766b503f) --- 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 53baa8456e..133991228c 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);
