From 0aef5a3184f7d34f78e3e540915331e0717a7d18 Mon Sep 17 00:00:00 2001 From: Robert McConnell Date: Mon, 14 Sep 2026 05:37:37 +0000 Subject: [PATCH] mod_substitute: enforce max line length on unmatched tail Account for the unmatched tail after a successful substitution before emitting the result. This keeps SubstituteMaxLineLength effective for flattened literal substitutions and for both regular-expression paths. --- changes-entries/substitute-maxlinelength-tail.txt | 2 ++ modules/filters/mod_substitute.c | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 changes-entries/substitute-maxlinelength-tail.txt diff --git a/changes-entries/substitute-maxlinelength-tail.txt b/changes-entries/substitute-maxlinelength-tail.txt new file mode 100644 index 00000000000..301d1aac66e --- /dev/null +++ b/changes-entries/substitute-maxlinelength-tail.txt @@ -0,0 +1,2 @@ + *) mod_substitute: Enforce SubstituteMaxLineLength on the unmatched tail + after substitutions. [Robert McConnell] diff --git a/modules/filters/mod_substitute.c b/modules/filters/mod_substitute.c index 2533d7dcd04..c78992c4833 100644 --- a/modules/filters/mod_substitute.c +++ b/modules/filters/mod_substitute.c @@ -282,8 +282,12 @@ static apr_status_t do_pattmatch(ap_filter_t *f, apr_bucket *inb, /* XXX: we should check for AP_MAX_BUCKETS here and * XXX: call ap_pass_brigade accordingly */ - char *copy = ap_varbuf_pdup(pool, &vb, NULL, 0, - buff, bytes, &len); + char *copy; + if (vb.strlen > cfg->max_line_length + || bytes > cfg->max_line_length - vb.strlen) + return APR_ENOMEM; + copy = ap_varbuf_pdup(pool, &vb, NULL, 0, + buff, bytes, &len); ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, f->r, "New line (%" APR_SIZE_T_FMT " bytes): %.*s", len, CAP2LINEMAX(len), copy); @@ -389,6 +393,9 @@ static apr_status_t do_pattmatch(ap_filter_t *f, apr_bucket *inb, /* Copy result plus the part after the last match into * a bucket. */ + if (vb.strlen > cfg->max_line_length + || left > cfg->max_line_length - vb.strlen) + return APR_ENOMEM; copy = ap_varbuf_pdup(pool, &vb, NULL, 0, pos, left, &len); ap_log_rerror(APLOG_MARK, APLOG_TRACE8, 0, f->r, @@ -400,6 +407,9 @@ static apr_status_t do_pattmatch(ap_filter_t *f, apr_bucket *inb, apr_bucket_delete(b); b = tmp_b; } + else if (have_match && left > space_left) { + return APR_ENOMEM; + } } else { ap_assert(0);