diff --git a/t/conf/proxy.conf.in b/t/conf/proxy.conf.in
index 37c76e65..5924d89c 100644
--- a/t/conf/proxy.conf.in
+++ b/t/conf/proxy.conf.in
@@ -338,6 +338,28 @@ Alias /modules/proxy/fcgi-uds-sethandler @SERVERROOT@/htdocs/modules/proxy/fcgi
ProxyPass http://@SERVERNAME@:@PORT@/modules/proxy_html
+ # Multi-substitution buffer reallocation test
+
+ ProxyHTMLEnable on
+ ProxyHTMLExtended on
+ ProxyHTMLLinks a href
+ ProxyHTMLEvents onclick
+ ProxyHTMLBufSize 256
+ ProxyHTMLURLMap http://x/ http://long-rewritten-path.example.com/
+ ProxyPass http://@SERVERNAME@:@PORT@/modules/proxy_html
+
+
+ # Multi-substitution regex buffer test
+
+ ProxyHTMLEnable on
+ ProxyHTMLExtended on
+ ProxyHTMLLinks a href
+ ProxyHTMLEvents onclick
+ ProxyHTMLBufSize 256
+ ProxyHTMLURLMap "http://rx/" "http://regex-rewritten-path.example.com/" R
+ ProxyPass http://@SERVERNAME@:@PORT@/modules/proxy_html
+
+
# Multiple URL maps test
ProxyHTMLEnable on
diff --git a/t/htdocs/modules/proxy_html/multi_subst.html b/t/htdocs/modules/proxy_html/multi_subst.html
new file mode 100644
index 00000000..0598dba5
--- /dev/null
+++ b/t/htdocs/modules/proxy_html/multi_subst.html
@@ -0,0 +1,20 @@
+
+
+Multi-substitution buffer test
+
+
+test
+
+
+
+
+Multi-substitution buffer test
+
+
+test
+
+
diff --git a/t/htdocs/modules/proxy_html/multi_subst_rx.html b/t/htdocs/modules/proxy_html/multi_subst_rx.html
new file mode 100644
index 00000000..1d838df1
--- /dev/null
+++ b/t/htdocs/modules/proxy_html/multi_subst_rx.html
@@ -0,0 +1,20 @@
+
+
+Multi-substitution regex buffer test
+
+
+test
+
+
+
+
+Multi-substitution regex buffer test
+
+
+test
+
+
diff --git a/t/modules/proxy_html.t b/t/modules/proxy_html.t
index e57d8ad9..4212ebc8 100644
--- a/t/modules/proxy_html.t
+++ b/t/modules/proxy_html.t
@@ -132,6 +132,30 @@ my @tests = (
{ type => 'url_rewrite', path => 'doctype/doctype.html',
pattern => ' 'DOCTYPE declaration added' },
+ # Multi-substitution buffer reallocation tests
+ # Tests that many literal substitutions (where replacement > match) in a
+ # single buffer don't truncate content when ap_varbuf_grow reallocates.
+ { type => 'url_rewrite', path => 'multi_subst/multi_subst.html',
+ pattern => 'http://long-rewritten-path\\.example\\.com/u01', desc => 'CDATA multi-subst first URL rewritten' },
+ { type => 'url_rewrite', path => 'multi_subst/multi_subst.html',
+ pattern => 'http://long-rewritten-path\\.example\\.com/u40', desc => 'CDATA multi-subst last URL rewritten' },
+ { type => 'url_rewrite', path => 'multi_subst/multi_subst.html',
+ pattern => 'CDATA_END_OK', desc => 'CDATA content preserved after multi-substitution' },
+ { type => 'url_rewrite', path => 'multi_subst/multi_subst.html',
+ pattern => 'EVENT_END_OK', desc => 'event attr preserved after multi-substitution' },
+
+ # Multi-substitution regex buffer tests
+ # Tests that many regex substitutions in a single CDATA/event buffer
+ # don't cause heap overflow or content truncation.
+ { type => 'url_rewrite', path => 'multi_subst_rx/multi_subst_rx.html',
+ pattern => 'http://regex-rewritten-path\\.example\\.com/u01', desc => 'CDATA regex multi-subst first URL rewritten' },
+ { type => 'url_rewrite', path => 'multi_subst_rx/multi_subst_rx.html',
+ pattern => 'http://regex-rewritten-path\\.example\\.com/u40', desc => 'CDATA regex multi-subst last URL rewritten' },
+ { type => 'url_rewrite', path => 'multi_subst_rx/multi_subst_rx.html',
+ pattern => 'RX_CDATA_END_OK', desc => 'CDATA content preserved after regex multi-substitution' },
+ { type => 'url_rewrite', path => 'multi_subst_rx/multi_subst_rx.html',
+ pattern => 'RX_EVENT_END_OK', desc => 'event attr preserved after regex multi-substitution' },
+
# Multiple URL maps tests
{ type => 'url_rewrite', path => 'multiple_maps/multiple_maps.html',
pattern => 'http://new-a\\.example\\.com/page1\\.html', desc => 'first URL map' },