Resolves: RHEL-186198 - httpd: Apache HTTP Server: Heap-based Buffer Overflow

via untrusted content in mod_xml2enc (CVE-2026-42536)
Resolves: RHEL-186166 - httpd: Apache HTTP Server: Buffer Over-read via
  outbound OCSP requests to attacker-controlled server (CVE-2026-44185)
Resolves: RHEL-175620 - httpd:2.4/httpd: NULL pointer dereference via
  specially crafted request (CVE-2026-29169)
Resolves: RHEL-186176 - httpd: Apache HTTP Server: Buffer overflow in
  mod_proxy_html allows security bypass (CVE-2026-34355)
Resolves: RHEL-192751 - mod_proxy_html regression in CVE-2026-34355 fix
Resolves: RHEL-193114 - httpd: Apache HTTP Server: Denial of Service
  in mod_proxy_ftp via attacker-controlled FTP server (CVE-2026-44186)
Resolves: RHEL-186219 - httpd: Apache HTTP Server: Heap-based Buffer Overflow
  via malicious backend servers (CVE-2026-34356)
Resolves: RHEL-191243 - httpd: Apache HTTP Server: Out-of-bounds Read in
  mod_headers and mod_mime (CVE-2026-43951)
Resolves: RHEL-184307 - httpd: Apache HTTP Server: Denial of Service via
  crafted regular expressions (CVE-2026-44631)
Resolves: RHEL-182577 - httpd: incomplete fix
  for CVE-2023-38709 (CVE-2024-42516)
This commit is contained in:
Luboš Uhliarik 2026-07-14 19:48:51 +02:00
parent c33900c646
commit 7ea902ca62
10 changed files with 1191 additions and 1 deletions

View File

@ -0,0 +1,326 @@
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index 8ac2cb4..790351d 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -1284,107 +1284,10 @@ typedef struct header_filter_ctx {
int headers_sent;
} header_filter_ctx;
-AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
- apr_bucket_brigade *b)
+static void merge_response_headers(request_rec *r, const char **protocol)
{
- request_rec *r = f->r;
- conn_rec *c = r->connection;
- const char *clheader;
- int header_only = (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status));
- const char *protocol = NULL;
- apr_bucket *e;
- apr_bucket_brigade *b2;
- header_struct h;
- header_filter_ctx *ctx = f->ctx;
- const char *ctype;
- ap_bucket_error *eb = NULL;
- apr_status_t rv = APR_SUCCESS;
- int recursive_error = 0;
-
- AP_DEBUG_ASSERT(!r->main);
-
- if (!ctx) {
- ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx));
- }
- else if (ctx->headers_sent) {
- /* Eat body if response must not have one. */
- if (header_only) {
- /* Still next filters may be waiting for EOS, so pass it (alone)
- * when encountered and be done with this filter.
- */
- e = APR_BRIGADE_LAST(b);
- if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) {
- APR_BUCKET_REMOVE(e);
- apr_brigade_cleanup(b);
- APR_BRIGADE_INSERT_HEAD(b, e);
- ap_remove_output_filter(f);
- rv = ap_pass_brigade(f->next, b);
- }
- apr_brigade_cleanup(b);
- return rv;
- }
- }
-
- for (e = APR_BRIGADE_FIRST(b);
- e != APR_BRIGADE_SENTINEL(b);
- e = APR_BUCKET_NEXT(e))
- {
- if (AP_BUCKET_IS_ERROR(e) && !eb) {
- eb = e->data;
- continue;
- }
- /*
- * If we see an EOC bucket it is a signal that we should get out
- * of the way doing nothing.
- */
- if (AP_BUCKET_IS_EOC(e)) {
- ap_remove_output_filter(f);
- return ap_pass_brigade(f->next, b);
- }
- }
-
- if (!ctx->headers_sent && !check_headers(r)) {
- /* We may come back here from ap_die() below,
- * so clear anything from this response.
- */
- apr_table_clear(r->headers_out);
- apr_table_clear(r->err_headers_out);
- r->content_type = r->content_encoding = NULL;
- r->content_languages = NULL;
- r->clength = r->chunked = 0;
- apr_brigade_cleanup(b);
-
- /* Don't recall ap_die() if we come back here (from its own internal
- * redirect or error response), otherwise we can end up in infinite
- * recursion; better fall through with 500, minimal headers and an
- * empty body (EOS only).
- */
- if (!check_headers_recursion(r)) {
- ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
- return AP_FILTER_ERROR;
- }
- r->status = HTTP_INTERNAL_SERVER_ERROR;
- e = ap_bucket_eoc_create(c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- e = apr_bucket_eos_create(c->bucket_alloc);
- APR_BRIGADE_INSERT_TAIL(b, e);
- ap_set_content_length(r, 0);
- recursive_error = 1;
- }
- else if (eb) {
- int status;
- status = eb->status;
- apr_brigade_cleanup(b);
- ap_die(status, r);
- return AP_FILTER_ERROR;
- }
-
- if (r->assbackwards) {
- r->sent_bodyct = 1;
- ap_remove_output_filter(f);
- rv = ap_pass_brigade(f->next, b);
- goto out;
- }
+ const char *ctype = NULL;
+ const char *clheader = NULL;
/*
* Now that we are ready to send a response, we need to combine the two
@@ -1414,6 +1317,9 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
fixup_vary(r);
}
+ /* determine the protocol and whether we should use keepalives. */
+ basic_http_header_check(r, protocol);
+ ap_set_keepalive(r);
/*
* Control cachability for non-cacheable responses if not already set by
@@ -1433,10 +1339,6 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
apr_table_unset(r->headers_out, "ETag");
}
- /* determine the protocol and whether we should use keepalives. */
- basic_http_header_check(r, &protocol);
- ap_set_keepalive(r);
-
/* 204/304 responses don't have content related headers */
if (AP_STATUS_IS_HEADER_ONLY(r->status)) {
apr_table_unset(r->headers_out, "Transfer-Encoding");
@@ -1497,49 +1399,156 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
&& !strcmp(clheader, "0")) {
apr_table_unset(r->headers_out, "Content-Length");
}
+}
- b2 = apr_brigade_create(r->pool, c->bucket_alloc);
- basic_http_header(r, b2, protocol);
+AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
+ apr_bucket_brigade *b)
+{
+ request_rec *r = f->r;
+ conn_rec *c = r->connection;
+ int header_only = (r->header_only || AP_STATUS_IS_HEADER_ONLY(r->status));
+ apr_bucket *e;
+ apr_bucket_brigade *b2;
+ header_struct h;
+ header_filter_ctx *ctx = f->ctx;
+ ap_bucket_error *eb = NULL;
+ apr_status_t rv = APR_SUCCESS;
+ int recursive_error = 0;
+ const char *protocol;
- h.pool = r->pool;
- h.bb = b2;
-
- if (r->status == HTTP_NOT_MODIFIED) {
- apr_table_do((int (*)(void *, const char *, const char *)) form_header_field,
- (void *) &h, r->headers_out,
- "Connection",
- "Keep-Alive",
- "ETag",
- "Content-Location",
- "Expires",
- "Cache-Control",
- "Vary",
- "Warning",
- "WWW-Authenticate",
- "Proxy-Authenticate",
- "Set-Cookie",
- "Set-Cookie2",
- NULL);
+ AP_DEBUG_ASSERT(!r->main);
+
+ if (!ctx) {
+ ctx = f->ctx = apr_pcalloc(r->pool, sizeof(header_filter_ctx));
}
- else {
- send_all_header_fields(&h, r);
+ else if (ctx->headers_sent) {
+ /* Eat body if response must not have one. */
+ if (header_only) {
+ /* Still next filters may be waiting for EOS, so pass it (alone)
+ * when encountered and be done with this filter.
+ */
+ e = APR_BRIGADE_LAST(b);
+ if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) {
+ APR_BUCKET_REMOVE(e);
+ apr_brigade_cleanup(b);
+ APR_BRIGADE_INSERT_HEAD(b, e);
+ ap_remove_output_filter(f);
+ rv = ap_pass_brigade(f->next, b);
+ }
+ apr_brigade_cleanup(b);
+ return rv;
+ }
}
- terminate_header(b2);
- if (header_only) {
- e = APR_BRIGADE_LAST(b);
- if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) {
- APR_BUCKET_REMOVE(e);
- APR_BRIGADE_INSERT_TAIL(b2, e);
+ for (e = APR_BRIGADE_FIRST(b);
+ e != APR_BRIGADE_SENTINEL(b);
+ e = APR_BUCKET_NEXT(e))
+ {
+ if (AP_BUCKET_IS_ERROR(e) && !eb) {
+ eb = e->data;
+ continue;
+ }
+ /*
+ * If we see an EOC bucket it is a signal that we should get out
+ * of the way doing nothing.
+ */
+ if (AP_BUCKET_IS_EOC(e)) {
ap_remove_output_filter(f);
+ return ap_pass_brigade(f->next, b);
+ }
+ }
+
+ if (!ctx->headers_sent) {
+ merge_response_headers(r, &protocol);
+ if (!check_headers(r)) {
+ /* We may come back here from ap_die() below,
+ * so clear anything from this response.
+ */
+ apr_table_clear(r->headers_out);
+ apr_table_clear(r->err_headers_out);
+ r->content_type = r->content_encoding = NULL;
+ r->content_languages = NULL;
+ r->clength = r->chunked = 0;
+ apr_brigade_cleanup(b);
+
+ /* Don't recall ap_die() if we come back here (from its own internal
+ * redirect or error response), otherwise we can end up in infinite
+ * recursion; better fall through with 500, minimal headers and an
+ * empty body (EOS only).
+ */
+ if (!check_headers_recursion(r)) {
+ ap_die(HTTP_INTERNAL_SERVER_ERROR, r);
+ return AP_FILTER_ERROR;
+ }
+ r->status = HTTP_INTERNAL_SERVER_ERROR;
+ e = ap_bucket_eoc_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ e = apr_bucket_eos_create(c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ ap_set_content_length(r, 0);
+ recursive_error = 1;
+ }
+ else if (eb) {
+ int status;
+ status = eb->status;
+ apr_brigade_cleanup(b);
+ ap_die(status, r);
+ return AP_FILTER_ERROR;
}
- apr_brigade_cleanup(b);
}
- rv = ap_pass_brigade(f->next, b2);
- apr_brigade_cleanup(b2);
- ctx->headers_sent = 1;
+ if (r->assbackwards) {
+ r->sent_bodyct = 1;
+ ap_remove_output_filter(f);
+ rv = ap_pass_brigade(f->next, b);
+ goto out;
+ }
+
+ if (!ctx->headers_sent) {
+ b2 = apr_brigade_create(r->pool, c->bucket_alloc);
+ basic_http_header(r, b2, protocol);
+
+ h.pool = r->pool;
+ h.bb = b2;
+
+ if (r->status == HTTP_NOT_MODIFIED) {
+ apr_table_do((int (*)(void *, const char *, const char *)) form_header_field,
+ (void *) &h, r->headers_out,
+ "Connection",
+ "Keep-Alive",
+ "ETag",
+ "Content-Location",
+ "Expires",
+ "Cache-Control",
+ "Vary",
+ "Warning",
+ "WWW-Authenticate",
+ "Proxy-Authenticate",
+ "Set-Cookie",
+ "Set-Cookie2",
+ NULL);
+ }
+ else {
+ send_all_header_fields(&h, r);
+ }
+
+ terminate_header(b2);
+
+ if (header_only) {
+ e = APR_BRIGADE_LAST(b);
+ if (e != APR_BRIGADE_SENTINEL(b) && APR_BUCKET_IS_EOS(e)) {
+ APR_BUCKET_REMOVE(e);
+ APR_BRIGADE_INSERT_TAIL(b2, e);
+ ap_remove_output_filter(f);
+ }
+ apr_brigade_cleanup(b);
+ }
+
+ rv = ap_pass_brigade(f->next, b2);
+ apr_brigade_cleanup(b2);
+ ctx->headers_sent = 1;
+ }
if (rv != APR_SUCCESS || header_only) {
goto out;

View File

@ -0,0 +1,39 @@
From 6736911b0b1dac27bae9fb36514008bc5dae8602 Mon Sep 17 00:00:00 2001
From: Eric Covener <covener@apache.org>
Date: Sun, 26 Apr 2026 16:04:35 +0000
Subject: [PATCH] Merge r1933353 from trunk:
mod_dav_lock: use the right dav_lock_discovery
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1933354 13f79535-47bb-0310-9956-ffa450edef68
---
modules/dav/lock/locks.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/modules/dav/lock/locks.c b/modules/dav/lock/locks.c
index 17b9ee6..fc354fa 100644
--- a/modules/dav/lock/locks.c
+++ b/modules/dav/lock/locks.c
@@ -1164,13 +1164,13 @@ static dav_error * dav_generic_refresh_locks(dav_lockdb *lockdb,
}
if (dav_generic_do_refresh(dp_scan, ltl, new_time)) {
/* the lock was refreshed. return the lock. */
- newlock = dav_generic_alloc_lock(lockdb, ip->key, dp->locktoken);
+ newlock = dav_generic_alloc_lock(lockdb, ip->key, dp_scan->locktoken);
newlock->is_locknull = !resource->exists;
- newlock->scope = dp->f.scope;
- newlock->type = dp->f.type;
- newlock->depth = dp->f.depth;
- newlock->timeout = dp->f.timeout;
- newlock->owner = dp->owner;
+ newlock->scope = dp_scan->f.scope;
+ newlock->type = dp_scan->f.type;
+ newlock->depth = dp_scan->f.depth;
+ newlock->timeout = dp_scan->f.timeout;
+ newlock->owner = dp_scan->owner;
newlock->auth_user = dp_scan->auth_user;
newlock->next = *locks;
--
2.44.0

View File

@ -0,0 +1,571 @@
From 9b1cfbb0f943577029dcad69f8f7652dc55897b2 Mon Sep 17 00:00:00 2001
From: Joe Orton <jorton@apache.org>
Date: Thu, 4 Jun 2026 11:22:27 +0000
Subject: [PATCH] Merge r1934975 from trunk:
mod_proxy_html: Simplify to use the ap_varbuf API.
* modules/filters/mod_proxy_html.c: Include util_varbuf.h.
(saxctxt): Replace buf/offset/avail members with struct ap_varbuf vb.
(DEFAULT_BUFSZ): New macro.
(normalise): Take struct ap_varbuf * parameter instead of char *.
(preserve, pappend): Remove functions, replaced by ap_varbuf_grow
and ap_varbuf_strmemcat respectively.
(dump_content): Use ap_varbuf for regex substitutions via
ap_varbuf_regsub, avoiding manual buffer resizing with
preserve/memmove/memcpy. Use a temporary ap_varbuf for building
regex replacement results.
(pcharacters, pcomment): Use ap_varbuf_strmemcat and ap_varbuf_strcat
in place of pappend.
(pendElement): Check vb.strlen instead of offset.
(pstartElement): Use ap_varbuf for attribute URL rewriting with the
same ap_varbuf_regsub approach. Use a temporary ap_varbuf for
regex replacements.
(proxy_html_filter): Initialize the ap_varbuf with a clamped bufsz.
(proxy_html_merge): Use DEFAULT_BUFSZ macro.
Assisted-by: Claude Opus 4.6 (claude-opus-4-6)
Reviewed by: covener, jfclere, jorton
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1934977 13f79535-47bb-0310-9956-ffa450edef68
---
modules/filters/mod_proxy_html.c | 270 ++++++++++++++-----------------
1 file changed, 121 insertions(+), 149 deletions(-)
diff --git a/modules/filters/mod_proxy_html.c b/modules/filters/mod_proxy_html.c
index 8b619e8..8b8e505 100644
--- a/modules/filters/mod_proxy_html.c
+++ b/modules/filters/mod_proxy_html.c
@@ -44,6 +44,7 @@
#include "mod_xml2enc.h"
#include "http_request.h"
#include "ap_expr.h"
+#include "util_varbuf.h"
/* globals set once at startup */
static ap_rxplus_t *old_expr;
@@ -103,9 +104,7 @@ typedef struct {
proxy_html_conf *cfg;
htmlParserCtxtPtr parser;
apr_bucket_brigade *bb;
- char *buf;
- size_t offset;
- size_t avail;
+ struct ap_varbuf vb;
const char *encoding;
urlmap *map;
char rbuf[4];
@@ -113,6 +112,7 @@ typedef struct {
apr_size_t rmin;
} saxctxt;
+#define DEFAULT_BUFSZ (8192)
#define NORM_LC 0x1
#define NORM_MSSLASH 0x2
@@ -136,17 +136,17 @@ static const char *const xhtml_etag = " />";
static const char *const DEFAULT_DOCTYPE = "";
#define DEFAULT_ETAG html_etag
-static void normalise(unsigned int flags, char *str)
+static void normalise(unsigned int flags, struct ap_varbuf *vb)
{
- char *p;
+ apr_size_t n;
if (flags & NORM_LC)
- for (p = str; *p; ++p)
- if (isupper(*p))
- *p = tolower(*p);
+ for (n = 0; n < vb->strlen; ++n)
+ vb->buf[n] = apr_tolower(vb->buf[n]);
if (flags & NORM_MSSLASH)
- for (p = ap_strchr(str, '\\'); p; p = ap_strchr(p+1, '\\'))
- *p = '/';
+ for (n = 0; n < vb->strlen; ++n)
+ if (vb->buf[n] == '\\')
+ vb->buf[n] = '/';
}
#define consume_buffer(ctx,inbuf,bytes,flag) \
@@ -175,120 +175,97 @@ static void pcharacters(void *ctxt, const xmlChar *uchars, int length)
FLUSH;
}
-static void preserve(saxctxt *ctx, const size_t len)
-{
- char *newbuf;
- if (len <= (ctx->avail - ctx->offset))
- return;
- else while (len > (ctx->avail - ctx->offset))
- ctx->avail += ctx->cfg->bufsz;
-
- newbuf = realloc(ctx->buf, ctx->avail);
- if (newbuf != ctx->buf) {
- if (ctx->buf)
- apr_pool_cleanup_kill(ctx->f->r->pool, ctx->buf,
- (int(*)(void*))free);
- apr_pool_cleanup_register(ctx->f->r->pool, newbuf,
- (int(*)(void*))free, apr_pool_cleanup_null);
- ctx->buf = newbuf;
- }
-}
-
-static void pappend(saxctxt *ctx, const char *buf, const size_t len)
-{
- preserve(ctx, len);
- memcpy(ctx->buf+ctx->offset, buf, len);
- ctx->offset += len;
-}
-
static void dump_content(saxctxt *ctx)
{
urlmap *m;
char *found;
size_t s_from, s_to;
size_t match;
- char c = 0;
int nmatch;
ap_regmatch_t pmatch[10];
- char *subs;
size_t len, offs;
urlmap *themap = ctx->map;
+ struct ap_varbuf temp;
#ifndef GO_FASTER
int verbose = APLOGrtrace1(ctx->f->r);
#endif
- pappend(ctx, &c, 1); /* append null byte */
- /* parse the text for URLs */
+ /* Ensure buffer is null-terminated and strlen is set */
+ if (ctx->vb.strlen == AP_VARBUF_UNKNOWN) {
+ ctx->vb.strlen = strlen(ctx->vb.buf);
+ }
+
+ ap_varbuf_init(ctx->f->r->pool, &temp, 0);
+
+ /* parse the text for URLs */
for (m = themap; m; m = m->next) {
if (!(m->flags & M_CDATA))
continue;
if (m->flags & M_REGEX) {
+ temp.strlen = 0;
nmatch = 10;
offs = 0;
- while (!ap_regexec(m->from.r, ctx->buf+offs, nmatch, pmatch, 0)) {
+ while (!ap_regexec(m->from.r, ctx->vb.buf+offs, nmatch, pmatch, 0)) {
match = pmatch[0].rm_so;
s_from = pmatch[0].rm_eo - match;
- subs = ap_pregsub(ctx->f->r->pool, m->to, ctx->buf+offs,
- nmatch, pmatch);
- s_to = strlen(subs);
- len = strlen(ctx->buf);
- offs += match;
VERBOSEB(
const char *f = apr_pstrndup(ctx->f->r->pool,
- ctx->buf + offs, s_from);
+ ctx->vb.buf + offs + match, s_from);
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, ctx->f->r,
- "C/RX: match at %s, substituting %s", f, subs);
+ "C/RX: match at %s, substituting with pattern %s",
+ f, m->to);
)
- if (s_to > s_from) {
- preserve(ctx, s_to - s_from);
- memmove(ctx->buf+offs+s_to, ctx->buf+offs+s_from,
- len + 1 - s_from - offs);
- memcpy(ctx->buf+offs, subs, s_to);
- }
- else {
- memcpy(ctx->buf + offs, subs, s_to);
- memmove(ctx->buf+offs+s_to, ctx->buf+offs+s_from,
- len + 1 - s_from - offs);
- }
- offs += s_to;
+ /* Copy text before the match */
+ ap_varbuf_strmemcat(&temp, ctx->vb.buf+offs, match);
+ /* Append the substitution */
+ ap_varbuf_regsub(&temp, m->to, ctx->vb.buf+offs, nmatch, pmatch, 0);
+ /* Continue past the match */
+ offs += pmatch[0].rm_eo;
}
+ /* Copy any remaining text */
+ ap_varbuf_strcat(&temp, ctx->vb.buf+offs);
+ /* Replace the original buffer with the result */
+ ctx->vb.strlen = 0;
+ ap_varbuf_strmemcat(&ctx->vb, temp.buf, temp.strlen);
}
else {
s_from = strlen(m->from.c);
s_to = strlen(m->to);
- for (found = strstr(ctx->buf, m->from.c); found;
- found = strstr(ctx->buf+match+s_to, m->from.c)) {
- match = found - ctx->buf;
+ for (found = strstr(ctx->vb.buf, m->from.c); found;
+ found = strstr(ctx->vb.buf+match+s_to, m->from.c)) {
+ match = found - ctx->vb.buf;
if ((m->flags & M_ATSTART) && (match != 0))
break;
- len = strlen(ctx->buf);
+ len = ctx->vb.strlen;
if ((m->flags & M_ATEND) && (match < (len - s_from)))
continue;
VERBOSE(ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0, ctx->f->r,
"C: matched %s, substituting %s",
m->from.c, m->to));
if (s_to > s_from) {
- preserve(ctx, s_to - s_from);
- memmove(ctx->buf+match+s_to, ctx->buf+match+s_from,
+ ap_varbuf_grow(&ctx->vb, len + s_to - s_from);
+ memmove(ctx->vb.buf+match+s_to, ctx->vb.buf+match+s_from,
len + 1 - s_from - match);
- memcpy(ctx->buf+match, m->to, s_to);
+ memcpy(ctx->vb.buf+match, m->to, s_to);
}
else {
- memcpy(ctx->buf+match, m->to, s_to);
- memmove(ctx->buf+match+s_to, ctx->buf+match+s_from,
+ memcpy(ctx->vb.buf+match, m->to, s_to);
+ memmove(ctx->vb.buf+match+s_to, ctx->vb.buf+match+s_from,
len + 1 - s_from - match);
}
+ ctx->vb.strlen = len - s_from + s_to;
}
}
}
- AP_fwrite(ctx, ctx->buf, strlen(ctx->buf), 1);
+ AP_fwrite(ctx, ctx->vb.buf, ctx->vb.strlen, 1);
+ ap_varbuf_free(&temp);
}
static void pcdata(void *ctxt, const xmlChar *uchars, int length)
{
const char *chars = (const char*) uchars;
saxctxt *ctx = (saxctxt*) ctxt;
if (ctx->cfg->extfix) {
- pappend(ctx, chars, length);
+ ap_varbuf_strmemcat(&ctx->vb, chars, length);
}
else {
/* not sure if this should force-flush
@@ -305,15 +282,14 @@ static void pcomment(void *ctxt, const xmlChar *uchars)
return;
if (ctx->cfg->extfix) {
- pappend(ctx, "<!--", 4);
- pappend(ctx, chars, strlen(chars));
- pappend(ctx, "-->", 3);
+ ap_varbuf_strcat(&ctx->vb, "<!--");
+ ap_varbuf_strcat(&ctx->vb, chars);
+ ap_varbuf_strcat(&ctx->vb, "-->");
}
else {
ap_fputs(ctx->f->next, ctx->bb, "<!--");
AP_fwrite(ctx, chars, strlen(chars), 1);
ap_fputs(ctx->f->next, ctx->bb, "-->");
- dump_content(ctx);
}
}
static void pendElement(void *ctxt, const xmlChar *uname)
@@ -337,9 +313,9 @@ static void pendElement(void *ctxt, const xmlChar *uname)
/* TODO - implement HTML "allowed here" using the stack */
/* nah. Keeping the stack is too much overhead */
- if (ctx->offset > 0) {
+ if (ctx->vb.strlen > 0) {
dump_content(ctx);
- ctx->offset = 0; /* having dumped it, we can re-use the memory */
+ ctx->vb.strlen = 0; /* having dumped it, we can re-use the memory */
}
if (!desc || !desc->empty) {
ap_fprintf(ctx->f->next, ctx->bb, "</%s>", name);
@@ -352,7 +328,6 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
int required_attrs;
int num_match;
size_t offs, len;
- char *subs;
rewrite_t is_uri;
const char** a;
urlmap *m;
@@ -370,6 +345,7 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
const char** attrs = (const char**) uattrs;
const htmlElemDesc* desc = htmlTagLookup(uname);
urlmap *themap = ctx->map;
+ struct ap_varbuf temp;
#ifdef HAVE_STACK
const void** descp;
#endif
@@ -399,6 +375,8 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
/* TODO - implement HTML "allowed here" */
#endif
+ ap_varbuf_init(ctx->f->r->pool, &temp, 0);
+
ap_fputc(ctx->f->next, ctx->bb, '<');
ap_fputs(ctx->f->next, ctx->bb, name);
@@ -429,9 +407,10 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
break;
}
}
- ctx->offset = 0;
+ ctx->vb.strlen = 0;
+ ctx->vb.buf[0] = '\0';
if (a[1]) {
- pappend(ctx, a[1], strlen(a[1])+1);
+ ap_varbuf_strcat(&ctx->vb, a[1]);
is_uri = ATTR_IGNORE;
if (linkattrs) {
tattr *attrs = (tattr*) linkattrs->elts;
@@ -460,59 +439,53 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
continue;
if (m->flags & M_REGEX) {
nmatch = 10;
- if (!ap_regexec(m->from.r, ctx->buf, nmatch,
+ if (!ap_regexec(m->from.r, ctx->vb.buf, nmatch,
pmatch, 0)) {
++num_match;
- offs = match = pmatch[0].rm_so;
+ match = pmatch[0].rm_so;
s_from = pmatch[0].rm_eo - match;
- subs = ap_pregsub(ctx->f->r->pool, m->to,
- ctx->buf, nmatch, pmatch);
VERBOSE({
const char *f;
f = apr_pstrndup(ctx->f->r->pool,
- ctx->buf + offs, s_from);
+ ctx->vb.buf + match, s_from);
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0,
ctx->f->r,
- "H/RX: match at %s, substituting %s",
- f, subs);
+ "H/RX: match at %s, substituting with pattern %s",
+ f, m->to);
})
- s_to = strlen(subs);
- len = strlen(ctx->buf);
- if (s_to > s_from) {
- preserve(ctx, s_to - s_from);
- memmove(ctx->buf+offs+s_to,
- ctx->buf+offs+s_from,
- len + 1 - s_from - offs);
- memcpy(ctx->buf+offs, subs, s_to);
- }
- else {
- memcpy(ctx->buf + offs, subs, s_to);
- memmove(ctx->buf+offs+s_to,
- ctx->buf+offs+s_from,
- len + 1 - s_from - offs);
- }
+ temp.strlen = 0;
+ /* Copy text before match */
+ ap_varbuf_strmemcat(&temp, ctx->vb.buf, match);
+ /* Append substitution */
+ ap_varbuf_regsub(&temp, m->to, ctx->vb.buf, nmatch, pmatch, 0);
+ /* Copy text after match */
+ ap_varbuf_strcat(&temp, ctx->vb.buf + pmatch[0].rm_eo);
+ /* Replace buffer */
+ ctx->vb.strlen = 0;
+ ap_varbuf_strmemcat(&ctx->vb, temp.buf, temp.strlen);
}
} else {
s_from = strlen(m->from.c);
- if (!strncasecmp(ctx->buf, m->from.c, s_from)) {
+ if (!strncasecmp(ctx->vb.buf, m->from.c, s_from)) {
++num_match;
s_to = strlen(m->to);
- len = strlen(ctx->buf);
+ len = ctx->vb.strlen;
VERBOSE(ap_log_rerror(APLOG_MARK, APLOG_TRACE3,
0, ctx->f->r,
"H: matched %s, substituting %s",
m->from.c, m->to));
if (s_to > s_from) {
- preserve(ctx, s_to - s_from);
- memmove(ctx->buf+s_to, ctx->buf+s_from,
+ ap_varbuf_grow(&ctx->vb, len + s_to - s_from);
+ memmove(ctx->vb.buf+s_to, ctx->vb.buf+s_from,
len + 1 - s_from);
- memcpy(ctx->buf, m->to, s_to);
+ memcpy(ctx->vb.buf, m->to, s_to);
}
else { /* it fits in the existing space */
- memcpy(ctx->buf, m->to, s_to);
- memmove(ctx->buf+s_to, ctx->buf+s_from,
+ memcpy(ctx->vb.buf, m->to, s_to);
+ memmove(ctx->vb.buf+s_to, ctx->vb.buf+s_from,
len + 1 - s_from);
}
+ ctx->vb.strlen = len - s_from + s_to;
break;
}
}
@@ -527,79 +500,73 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
if (!(m->flags & M_EVENTS))
continue;
if (m->flags & M_REGEX) {
+ temp.strlen = 0;
nmatch = 10;
offs = 0;
- while (!ap_regexec(m->from.r, ctx->buf+offs,
+ while (!ap_regexec(m->from.r, ctx->vb.buf+offs,
nmatch, pmatch, 0)) {
match = pmatch[0].rm_so;
s_from = pmatch[0].rm_eo - match;
- subs = ap_pregsub(ctx->f->r->pool, m->to, ctx->buf+offs,
- nmatch, pmatch);
VERBOSE({
const char *f;
f = apr_pstrndup(ctx->f->r->pool,
- ctx->buf + offs, s_from);
+ ctx->vb.buf + offs + match, s_from);
ap_log_rerror(APLOG_MARK, APLOG_TRACE3, 0,
ctx->f->r,
- "E/RX: match at %s, substituting %s",
- f, subs);
+ "E/RX: match at %s, substituting with pattern %s",
+ f, m->to);
})
- s_to = strlen(subs);
- offs += match;
- len = strlen(ctx->buf);
- if (s_to > s_from) {
- preserve(ctx, s_to - s_from);
- memmove(ctx->buf+offs+s_to,
- ctx->buf+offs+s_from,
- len + 1 - s_from - offs);
- memcpy(ctx->buf+offs, subs, s_to);
- }
- else {
- memcpy(ctx->buf + offs, subs, s_to);
- memmove(ctx->buf+offs+s_to,
- ctx->buf+offs+s_from,
- len + 1 - s_from - offs);
- }
- offs += s_to;
+ /* Copy text before match */
+ ap_varbuf_strmemcat(&temp, ctx->vb.buf+offs, match);
+ /* Append substitution */
+ ap_varbuf_regsub(&temp, m->to, ctx->vb.buf+offs, nmatch, pmatch, 0);
+ /* Continue past the match */
+ offs += pmatch[0].rm_eo;
++num_match;
}
+ /* Copy any remaining text */
+ ap_varbuf_strcat(&temp, ctx->vb.buf+offs);
+ /* Replace buffer */
+ ctx->vb.strlen = 0;
+ ap_varbuf_strmemcat(&ctx->vb, temp.buf, temp.strlen);
}
else {
- found = strstr(ctx->buf, m->from.c);
- if ((m->flags & M_ATSTART) && (found != ctx->buf))
+ found = strstr(ctx->vb.buf, m->from.c);
+ if ((m->flags & M_ATSTART) && (found != ctx->vb.buf))
continue;
while (found) {
s_from = strlen(m->from.c);
s_to = strlen(m->to);
- match = found - ctx->buf;
+ match = found - ctx->vb.buf;
if ((s_from < strlen(found))
&& (m->flags & M_ATEND)) {
- found = strstr(ctx->buf+match+s_from,
+ found = strstr(ctx->vb.buf+match+s_from,
m->from.c);
continue;
}
else {
- found = strstr(ctx->buf+match+s_to,
+ found = strstr(ctx->vb.buf+match+s_to,
m->from.c);
}
VERBOSE(ap_log_rerror(APLOG_MARK, APLOG_TRACE3,
0, ctx->f->r,
"E: matched %s, substituting %s",
m->from.c, m->to));
- len = strlen(ctx->buf);
+ len = ctx->vb.strlen;
if (s_to > s_from) {
- preserve(ctx, s_to - s_from);
- memmove(ctx->buf+match+s_to,
- ctx->buf+match+s_from,
+ ap_varbuf_grow(&ctx->vb, len + s_to - s_from);
+ memmove(ctx->vb.buf+match+s_to,
+ ctx->vb.buf+match+s_from,
len + 1 - s_from - match);
- memcpy(ctx->buf+match, m->to, s_to);
+ memcpy(ctx->vb.buf+match, m->to, s_to);
}
else {
- memcpy(ctx->buf+match, m->to, s_to);
- memmove(ctx->buf+match+s_to,
- ctx->buf+match+s_from,
+ memcpy(ctx->vb.buf+match, m->to, s_to);
+ memmove(ctx->vb.buf+match+s_to,
+ ctx->vb.buf+match+s_from,
len + 1 - s_from - match);
}
+ ctx->vb.strlen = len - s_from + s_to;
++num_match;
}
}
@@ -616,18 +583,18 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
else {
if (ctx->cfg->flags != 0)
- normalise(ctx->cfg->flags, ctx->buf);
+ normalise(ctx->cfg->flags, &ctx->vb);
/* write the attribute, using pcharacters to html-escape
anything that needs it in the value.
*/
ap_fputstrs(ctx->f->next, ctx->bb, " ", a[0], "=\"", NULL);
- pcharacters(ctx, (const xmlChar*)ctx->buf, strlen(ctx->buf));
+ pcharacters(ctx, (const xmlChar*)ctx->vb.buf, ctx->vb.strlen);
ap_fputc(ctx->f->next, ctx->bb, '"');
}
}
}
- ctx->offset = 0;
+ ctx->vb.strlen = 0;
if (desc && desc->empty)
ap_fputs(ctx->f->next, ctx->bb, ctx->cfg->etag);
else
@@ -639,6 +606,7 @@ static void pstartElement(void *ctxt, const xmlChar *uname,
"HTML element %s is missing %d required attributes",
name, required_attrs);
}
+ ap_varbuf_free(&temp);
}
static meta *metafix(request_rec *r, const char *buf, apr_size_t len)
@@ -807,6 +775,8 @@ static saxctxt *check_filter_init (ap_filter_t *f)
proxy_html_conf *cfg;
const char *force;
const char *errmsg = NULL;
+ apr_size_t bufsz;
+
cfg = ap_get_module_config(f->r->per_dir_config, &proxy_html_module);
force = apr_table_get(f->r->subprocess_env, "PROXY_HTML_FORCE");
@@ -840,6 +810,8 @@ static saxctxt *check_filter_init (ap_filter_t *f)
fctx->bb = apr_brigade_create(f->r->pool,
f->r->connection->bucket_alloc);
fctx->cfg = cfg;
+ bufsz = (cfg->bufsz <= 0 || cfg->bufsz > (128 * 1024)) ? DEFAULT_BUFSZ : cfg->bufsz;
+ ap_varbuf_init(f->r->pool, &fctx->vb, bufsz);
apr_table_unset(f->r->headers_out, "Content-Length");
if (cfg->interp)
@@ -1009,7 +981,7 @@ static void *proxy_html_config(apr_pool_t *pool, char *x)
proxy_html_conf *ret = apr_pcalloc(pool, sizeof(proxy_html_conf));
ret->doctype = DEFAULT_DOCTYPE;
ret->etag = DEFAULT_ETAG;
- ret->bufsz = 8192;
+ ret->bufsz = DEFAULT_BUFSZ;
/* ret->interp = 1; */
/* don't initialise links and events until they get set/used */
return ret;
--
2.44.0

View File

@ -0,0 +1,30 @@
diff --git a/modules/proxy/proxy_util.c b/modules/proxy/proxy_util.c
index f5c3283..012b6aa 100644
--- a/modules/proxy/proxy_util.c
+++ b/modules/proxy/proxy_util.c
@@ -982,6 +982,12 @@ PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r,
poffs = pathp - tmpstr_orig;
l1 = strlen(pathp);
pathe = str + poffs + l1;
+ /*
+ * RFC 6265 § 5.3 7): Only the last path= should be meaningful
+ * so reset anything previously found.
+ */
+ newpath = NULL;
+ pdiff = 0;
if (conf->interpolate_env == 1) {
ent = (struct proxy_alias *)rconf->cookie_paths->elts;
}
@@ -1002,6 +1008,12 @@ PROXY_DECLARE(const char *) ap_proxy_cookie_reverse_map(request_rec *r,
doffs = domainp - tmpstr_orig;
l1 = strlen(domainp);
domaine = str + doffs + l1;
+ /*
+ * RFC 6265 § 5.3 4): Only the last domain= should be meaningful
+ * so reset anything previously found.
+ */
+ newdomain = NULL;
+ ddiff = 0;
if (conf->interpolate_env == 1) {
ent = (struct proxy_alias *)rconf->cookie_domains->elts;
}

View File

@ -0,0 +1,25 @@
From 6fb79c31629bcbcb002dabb769602c20093c9aea Mon Sep 17 00:00:00 2001
From: Joe Orton <jorton@apache.org>
Date: Thu, 4 Jun 2026 08:46:03 +0000
Subject: [PATCH] * modules/filters/mod_xml2enc.c (fix_skipto): Fix accounting.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1934970 13f79535-47bb-0310-9956-ffa450edef68
---
modules/filters/mod_xml2enc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/modules/filters/mod_xml2enc.c b/modules/filters/mod_xml2enc.c
index dc4d021..5118d5b 100644
--- a/modules/filters/mod_xml2enc.c
+++ b/modules/filters/mod_xml2enc.c
@@ -145,6 +145,7 @@ static void fix_skipto(request_rec* r, xml2ctx* ctx)
apr_bucket_delete(b);
}
ctx->bytes -= (p-ctx->buf);
+ ctx->bblen -= (p-ctx->buf);
ctx->buf = p ;
found = 1;
ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01428)
--
2.44.0

View File

@ -0,0 +1,16 @@
diff --git a/modules/http/http_filters.c b/modules/http/http_filters.c
index bfa8952..8ac2cb4 100644
--- a/modules/http/http_filters.c
+++ b/modules/http/http_filters.c
@@ -1463,10 +1463,10 @@ AP_CORE_DECLARE_NONSTD(apr_status_t) ap_http_header_filter(ap_filter_t *f,
if (!apr_is_empty_array(r->content_languages)) {
int i;
char *token;
- char **languages = (char **)(r->content_languages->elts);
const char *field = apr_table_get(r->headers_out, "Content-Language");
while (field && (token = ap_get_list_item(r->pool, &field)) != NULL) {
+ char **languages = (char **)(r->content_languages->elts);
for (i = 0; i < r->content_languages->nelts; ++i) {
if (!strcasecmp(token, languages[i]))
break;

View File

@ -0,0 +1,30 @@
From 5310922061aec62914e8ffc19bbd6fb2ac52bab6 Mon Sep 17 00:00:00 2001
From: Joe Orton <jorton@apache.org>
Date: Wed, 3 Jun 2026 10:43:09 +0000
Subject: [PATCH] * modules/ssl/ssl_util_ocsp.c (send_request): Increase wbuf
with the len read by apr_socket_send
Submitted by: gbechis
Github: closes #603
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1934918 13f79535-47bb-0310-9956-ffa450edef68
---
modules/ssl/ssl_util_ocsp.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/modules/ssl/ssl_util_ocsp.c b/modules/ssl/ssl_util_ocsp.c
index b66e151..553ecde 100644
--- a/modules/ssl/ssl_util_ocsp.c
+++ b/modules/ssl/ssl_util_ocsp.c
@@ -132,7 +132,7 @@ static apr_socket_t *send_request(BIO *request, const apr_uri_t *uri,
apr_size_t wlen = remain;
rv = apr_socket_send(sd, wbuf, &wlen);
- wbuf += remain;
+ wbuf += wlen;
remain -= wlen;
} while (rv == APR_SUCCESS && remain > 0);
--
2.44.0

View File

@ -0,0 +1,18 @@
diff --git a/modules/proxy/mod_proxy_ftp.c b/modules/proxy/mod_proxy_ftp.c
index 5c4d641..a81028e 100644
--- a/modules/proxy/mod_proxy_ftp.c
+++ b/modules/proxy/mod_proxy_ftp.c
@@ -1243,10 +1243,12 @@ static int proxy_ftp_handler(request_rec *r, proxy_worker *worker,
time_t secs;
/* Look for a number, preceded by whitespace */
- while (*secs_str)
+ while (*secs_str) {
if ((secs_str==ftpmessage || apr_isspace(secs_str[-1])) &&
apr_isdigit(secs_str[0]))
break;
+ secs_str++;
+ }
if (*secs_str != '\0') {
secs = atol(secs_str);
apr_table_addn(r->headers_out, "Retry-After",

View File

@ -0,0 +1,87 @@
diff --git a/include/ap_regex.h b/include/ap_regex.h
index 7af2f99..6ff8eaa 100644
--- a/include/ap_regex.h
+++ b/include/ap_regex.h
@@ -187,6 +187,8 @@ AP_DECLARE(apr_size_t) ap_regerror(int errcode, const ap_regex_t *preg,
* @param preg The precompiled regex
* @param names The array to which the names will be added
* @param upper If non zero, uppercase the names
+ * @return number of regex backrefernces returned, -1 for error
+ * for successful match, AP_REG_NOMATCH otherwise
*/
AP_DECLARE(int) ap_regname(const ap_regex_t *preg,
apr_array_header_t *names, const char *prefix,
diff --git a/modules/proxy/mod_proxy.c b/modules/proxy/mod_proxy.c
index 16ebd98..06a6ad7 100644
--- a/modules/proxy/mod_proxy.c
+++ b/modules/proxy/mod_proxy.c
@@ -2597,7 +2597,9 @@ static const char *proxysection(cmd_parms *cmd, void *mconfig, const char *arg)
if (r) {
conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
- ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ if (ap_regname(r, conf->refs, AP_REG_MATCH, 1) < 0) {
+ return "Error processing regex captures";
+ }
}
ap_add_per_proxy_conf(cmd->server, new_dir_conf);
diff --git a/server/core.c b/server/core.c
index 1f99b3a..d9e366d 100644
--- a/server/core.c
+++ b/server/core.c
@@ -2423,7 +2423,9 @@ static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg)
if (r) {
conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
- ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ if (ap_regname(r, conf->refs, AP_REG_MATCH, 1) < 0) {
+ return "Error processing regex captures";
+ }
}
/* Make this explicit - the "/" root has 0 elements, that is, we
@@ -2504,7 +2506,9 @@ static const char *urlsection(cmd_parms *cmd, void *mconfig, const char *arg)
if (r) {
conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
- ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ if (ap_regname(r, conf->refs, AP_REG_MATCH, 1) < 0) {
+ return "Error processing regex captures";
+ }
}
ap_add_per_url_conf(cmd->server, new_url_conf);
@@ -2591,7 +2595,9 @@ static const char *filesection(cmd_parms *cmd, void *mconfig, const char *arg)
if (r) {
conf->refs = apr_array_make(cmd->pool, 8, sizeof(char *));
- ap_regname(r, conf->refs, AP_REG_MATCH, 1);
+ if (ap_regname(r, conf->refs, AP_REG_MATCH, 1) < 0) {
+ return "Error processing regex captures";
+ }
}
ap_add_file_conf(cmd->pool, (core_dir_config *)mconfig, new_file_conf);
diff --git a/server/util_pcre.c b/server/util_pcre.c
index 2a665c8..8fa672f 100644
--- a/server/util_pcre.c
+++ b/server/util_pcre.c
@@ -320,7 +320,16 @@ AP_DECLARE(int) ap_regname(const ap_regex_t *preg,
for (i = 0; i < namecount; i++) {
const char *offset = nametable + i * nameentrysize;
- int capture = ((offset[0] << 8) + offset[1]);
+ int capture = (((unsigned char)offset[0] << 8) + (unsigned char)offset[1]);
+
+ /* Sanity check: reject unreasonably large capture group numbers.
+ * PCRE allows up to 65535 groups, but such large numbers would
+ * cause excessive memory allocation. Limit to a reasonable maximum.
+ */
+ if (capture > 1024) {
+ return -1;
+ }
+
while (names->nelts <= capture) {
apr_array_push(names);
}

View File

@ -14,7 +14,7 @@
Summary: Apache HTTP Server
Name: httpd
Version: 2.4.37
Release: 65%{?dist}.8
Release: 65%{?dist}.9
URL: https://httpd.apache.org/
Source0: https://www.apache.org/dist/httpd/httpd-%{version}.tar.bz2
Source2: httpd.logrotate
@ -309,6 +309,24 @@ Patch257: httpd-2.4.37-CVE-2026-33857.patch
Patch258: httpd-2.4.37-CVE-2026-34032.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2464940
Patch259: httpd-2.4.37-CVE-2026-34059.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2486411
Patch260: httpd-2.4.37-CVE-2026-42536.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2486397
Patch261: httpd-2.4.37-CVE-2026-44185.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2465296
Patch262: httpd-2.4.37-CVE-2026-29169.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2486414
Patch263: httpd-2.4.37-CVE-2026-34355.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2486402
Patch264: httpd-2.4.37-CVE-2026-44186.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2486395
Patch265: httpd-2.4.37-CVE-2026-34356.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2486415
Patch266: httpd-2.4.37-CVE-2026-43951.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2486399
Patch267: httpd-2.4.37-CVE-2026-44631.patch
# https://bugzilla.redhat.com/show_bug.cgi?id=2374549
Patch268: httpd-2.4.37-CVE-2024-42516.patch
License: ASL 2.0
Group: System Environment/Daemons
@ -558,6 +576,15 @@ interface for storing and accessing per-user session data.
%patch257 -p1 -b .CVE-2026-33857
%patch258 -p1 -b .CVE-2026-34032
%patch259 -p1 -b .CVE-2026-34059
%patch260 -p1 -b .CVE-2026-42536
%patch261 -p1 -b .CVE-2026-44185
%patch262 -p1 -b .CVE-2026-29169
%patch263 -p1 -b .CVE-2026-34355
%patch264 -p1 -b .CVE-2026-44186
%patch265 -p1 -b .CVE-2026-34356
%patch266 -p1 -b .CVE-2026-43951
%patch267 -p1 -b .CVE-2026-44631
%patch268 -p1 -b .CVE-2024-42516
%patch96 -p1 -b .r1922080
@ -1069,6 +1096,27 @@ rm -rf $RPM_BUILD_ROOT
%{_rpmconfigdir}/macros.d/macros.httpd
%changelog
* Thu Jul 09 2026 Luboš Uhliarik <luhliari@redhat.com> - 2.4.37-65.9
- Resolves: RHEL-186198 - httpd: Apache HTTP Server: Heap-based Buffer Overflow
via untrusted content in mod_xml2enc (CVE-2026-42536)
- Resolves: RHEL-186166 - httpd: Apache HTTP Server: Buffer Over-read via
outbound OCSP requests to attacker-controlled server (CVE-2026-44185)
- Resolves: RHEL-175620 - httpd:2.4/httpd: NULL pointer dereference via
specially crafted request (CVE-2026-29169)
- Resolves: RHEL-186176 - httpd: Apache HTTP Server: Buffer overflow in
mod_proxy_html allows security bypass (CVE-2026-34355)
- Resolves: RHEL-192751 - mod_proxy_html regression in CVE-2026-34355 fix
- Resolves: RHEL-193114 - httpd: Apache HTTP Server: Denial of Service
in mod_proxy_ftp via attacker-controlled FTP server (CVE-2026-44186)
- Resolves: RHEL-186219 - httpd: Apache HTTP Server: Heap-based Buffer Overflow
via malicious backend servers (CVE-2026-34356)
- Resolves: RHEL-191243 - httpd: Apache HTTP Server: Out-of-bounds Read in
mod_headers and mod_mime (CVE-2026-43951)
- Resolves: RHEL-184307 - httpd: Apache HTTP Server: Denial of Service via
crafted regular expressions (CVE-2026-44631)
- Resolves: RHEL-182577 - httpd: incomplete fix
for CVE-2023-38709 (CVE-2024-42516)
* Tue May 12 2026 Luboš Uhliarik <luhliari@redhat.com> - 2.4.37-65.8
- Resolves: RHEL-173558 - httpd:2.4/httpd: Apache HTTP Server mod_proxy_ajp:
Arbitrary code execution via heap-based buffer overflow (CVE-2026-28780)