From 5e089ddcf54705c628f405fc6f6a64fef4212f48 Mon Sep 17 00:00:00 2001 From: arshiya tabasum Date: Fri, 2 Oct 2026 15:49:50 +0530 Subject: [PATCH] fix out-of-bounds read in mod_proxy_html metafix --- changes-entries/proxy-html-metafix-bounds.txt | 3 +++ modules/filters/mod_proxy_html.c | 21 ++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) create mode 100644 changes-entries/proxy-html-metafix-bounds.txt diff --git a/changes-entries/proxy-html-metafix-bounds.txt b/changes-entries/proxy-html-metafix-bounds.txt new file mode 100644 index 00000000000..3f55db8d7ef --- /dev/null +++ b/changes-entries/proxy-html-metafix-bounds.txt @@ -0,0 +1,3 @@ + *) mod_proxy_html: Fix out-of-bounds reads in metafix() when a + tag appears at the end of the response buffer with + ProxyHTMLMeta enabled. [Arshiya Tabasum] diff --git a/modules/filters/mod_proxy_html.c b/modules/filters/mod_proxy_html.c index a8c29db862a..afab76e8427 100644 --- a/modules/filters/mod_proxy_html.c +++ b/modules/filters/mod_proxy_html.c @@ -689,6 +689,7 @@ static meta *metafix(request_rec *r, const char *buf, apr_size_t len) size_t offs = 0; const char *p; const char *q; + const char *end = buf + len; char *header; char *content; ap_regmatch_t pmatch[2]; @@ -699,8 +700,8 @@ static meta *metafix(request_rec *r, const char *buf, apr_size_t len) header = NULL; content = NULL; p = buf+offs+pmatch[1].rm_eo; - while (!apr_isalpha(*++p)); - for (q = p; apr_isalnum(*q) || (*q == '-'); ++q); + while (++p < end && !apr_isalpha(*p)); + for (q = p; q < end && (apr_isalnum(*q) || (*q == '-')); ++q); header = apr_pstrmemdup(r->pool, p, q-p); if (!ap_cstr_casecmpn(header, "Content-Type", 12)) { ret = apr_palloc(r->pool, sizeof(meta)); @@ -713,22 +714,22 @@ static meta *metafix(request_rec *r, const char *buf, apr_size_t len) pmatch[0].rm_eo - pmatch[0].rm_so); /* if it doesn't contain "content", ignore, don't crash! */ if (p != NULL) { - while (*p) { + while (p < end && *p) { p += 7; - while (apr_isspace(*p)) + while (p < end && apr_isspace(*p)) ++p; /* XXX Should we search for another content= pattern? */ - if (*p != '=') + if (p >= end || *p != '=') break; - while (*p && apr_isspace(*++p)); - if ((*p == '\'') || (*p == '"')) { + while (++p < end && apr_isspace(*p)); + if (p < end && ((*p == '\'') || (*p == '"'))) { delim = *p++; - for (q = p; *q && *q != delim; ++q); + for (q = p; q < end && *q != delim; ++q); /* No terminating delimiter found? Skip the bogus directive */ - if (*q != delim) + if (q >= end || *q != delim) break; } else { - for (q = p; *q && !apr_isspace(*q) && (*q != '>'); ++q); + for (q = p; q < end && !apr_isspace(*q) && (*q != '>'); ++q); } content = apr_pstrmemdup(r->pool, p, q-p); break;