This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/9.0.x by this push:
new b477537e68 Fix regression in handling of chain rules
b477537e68 is described below
commit b477537e68acfcaa7220f90b512bf8a72bf237dc
Author: Mark Thomas <[email protected]>
AuthorDate: Mon Jul 20 14:50:50 2026 +0100
Fix regression in handling of chain rules
Test cases written using Claude / Opus 4.8
---
.../catalina/valves/rewrite/RewriteValve.java | 14 +++++------
.../catalina/valves/rewrite/TestRewriteValve.java | 28 ++++++++++++++++++++++
2 files changed, 34 insertions(+), 8 deletions(-)
diff --git a/java/org/apache/catalina/valves/rewrite/RewriteValve.java
b/java/org/apache/catalina/valves/rewrite/RewriteValve.java
index bc002f3984..923f6d5e16 100644
--- a/java/org/apache/catalina/valves/rewrite/RewriteValve.java
+++ b/java/org/apache/catalina/valves/rewrite/RewriteValve.java
@@ -537,15 +537,13 @@ public class RewriteValve extends ValveBase {
// - chain (skip remaining chained rules if this one does not
match)
if (rule.isChain() && newtest == null) {
- int skip = 0;
- for (int j = i + 1; j < rules.length; j++) {
- if (!rules[j].isChain()) {
- break;
- } else {
- skip++;
- }
+ // Skip the remaining rules in the chain, including the
+ // terminal rule that does not have the chain flag set.
+ int j = i + 1;
+ while (j < rules.length && rules[j].isChain()) {
+ j++;
}
- i += skip;
+ i = j;
continue;
}
// - last (stop rewriting here)
diff --git a/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
b/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
index 21118651d0..324f606edc 100644
--- a/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
+++ b/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
@@ -88,6 +88,34 @@ public class TestRewriteValve extends TomcatBaseTest {
doTestRewrite("RewriteRule ^/b/(.*) /b/../a/$1", "/b/%255A",
"/b/../a/%255A");
}
+ @Test
+ public void testChainMatch() throws Exception {
+ // The first rule matches so the chained (second) rule is applied to
the result
+ doTestRewrite("RewriteRule ^/a(.*) /b$1 [C]\n" +
+ "RewriteRule ^/b(.*) /c$1", "/a/x", "/c/x");
+ }
+
+ @Test
+ public void testChainHeadNoMatch() throws Exception {
+ // The first rule does not match so the whole chain, including the
+ // terminal rule that would otherwise match, must be skipped. If the
+ // terminal rule were incorrectly applied the request would be
rewritten
+ // to /W/x.
+ doTestRewrite("RewriteRule ^/never(.*) /c$1 [C]\n" +
+ "RewriteRule ^/c(.*) /W$1", "/c/x", "/c/x");
+ }
+
+ @Test
+ public void testChainMiddleNoMatch() throws Exception {
+ // The first rule matches but the second (chained) rule does not, so
the
+ // rest of the chain, including the terminal rule, must be skipped and
+ // the result of the first rule is retained. If the terminal rule were
+ // incorrectly applied the request would be rewritten to /W/y.
+ doTestRewrite("RewriteRule ^/a(.*) /c$1 [C]\n" +
+ "RewriteRule ^/nomatch(.*) /x$1 [C]\n" +
+ "RewriteRule ^/c(.*) /W$1", "/a/y", "/c/y");
+ }
+
// BZ 57863
@Test
public void testRewriteMap01() throws Exception {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]