This is an automated email from the ASF dual-hosted git repository.
markt-asf pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/main by this push:
new fb1a647ff8 Fix regression in handling of chain rules
fb1a647ff8 is described below
commit fb1a647ff83d080dc4af278a0ada149ece871915
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 8c839254df..a5f269f2dc 100644
--- a/java/org/apache/catalina/valves/rewrite/RewriteValve.java
+++ b/java/org/apache/catalina/valves/rewrite/RewriteValve.java
@@ -535,15 +535,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 9cfb79964c..ecf67047d5 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]