This is an automated email from the ASF dual-hosted git repository.
rmaucher 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 55bbf77cca Align the rewrite conditions ornext processing with
mod_rewrite
55bbf77cca is described below
commit 55bbf77cca0e90732c0e0bcff77d390a8bfa7c00
Author: remm <[email protected]>
AuthorDate: Thu Jun 4 21:17:10 2026 +0200
Align the rewrite conditions ornext processing with mod_rewrite
This now follows a sequential condition evaluation.
Test case co-authored with OpenCode.
---
.../catalina/valves/rewrite/RewriteRule.java | 8 ++++--
.../catalina/valves/rewrite/RewriteValve.java | 5 ----
.../catalina/valves/rewrite/TestRewriteValve.java | 30 ++++++++++++++++++++++
webapps/docs/changelog.xml | 5 ++++
4 files changed, 41 insertions(+), 7 deletions(-)
diff --git a/java/org/apache/catalina/valves/rewrite/RewriteRule.java
b/java/org/apache/catalina/valves/rewrite/RewriteRule.java
index d323895c68..49c0353636 100644
--- a/java/org/apache/catalina/valves/rewrite/RewriteRule.java
+++ b/java/org/apache/catalina/valves/rewrite/RewriteRule.java
@@ -159,8 +159,12 @@ public class RewriteRule {
if (lastMatcher2 != null) {
lastMatcher = lastMatcher2;
}
- while (pos < conditions.length &&
conditions[pos].isOrnext()) {
- pos++;
+ if (conditions[pos].isOrnext()) {
+ // Skip until the next condition not covered by the OR
+ // The rule immediately after the OR is covered
+ do {
+ pos++;
+ } while (pos < conditions.length &&
conditions[pos].isOrnext());
}
} else if (!conditions[pos].isOrnext()) {
done = true;
diff --git a/java/org/apache/catalina/valves/rewrite/RewriteValve.java
b/java/org/apache/catalina/valves/rewrite/RewriteValve.java
index 0cee5f365c..48e0c4eeec 100644
--- a/java/org/apache/catalina/valves/rewrite/RewriteValve.java
+++ b/java/org/apache/catalina/valves/rewrite/RewriteValve.java
@@ -278,11 +278,6 @@ public class RewriteValve extends ValveBase {
containerLog.trace("Add rule with pattern " +
rule.getPatternString() + " and substitution " +
rule.getSubstitutionString());
}
- for (int i = (conditions.size() - 1); i > 0; i--) {
- if (conditions.get(i - 1).isOrnext()) {
- conditions.get(i).setOrnext(true);
- }
- }
for (RewriteCond condition : conditions) {
if (containerLog.isTraceEnabled()) {
containerLog.trace("Add condition " +
condition.getCondPattern() + " test " +
diff --git a/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
b/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
index 9fa96c7d2d..5218aff5c4 100644
--- a/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
+++ b/test/org/apache/catalina/valves/rewrite/TestRewriteValve.java
@@ -1114,4 +1114,34 @@ public class TestRewriteValve extends TomcatBaseTest {
URLDecoder.decode(expectedSegment, StandardCharsets.UTF_8)));
Assert.assertTrue(body, body.contains("REQUEST-QUERY-STRING: " +
expectedQueryString));
}
+
+ @Test
+ public void testOrCondDoesNotSkipNonOrCond() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ Context ctx = getProgrammaticRootContext();
+
+ RewriteValve rewriteValve = new RewriteValve();
+ ctx.getPipeline().addValve(rewriteValve);
+
+ rewriteValve.setConfiguration(
+ "RewriteCond %{HTTP_HOST} localhost [OR]\n" +
+ "RewriteCond %{HTTP_HOST} 127.0.0.1\n" +
+ "RewriteCond %{REQUEST_URI} ^/admin\n" +
+ "RewriteRule ^(.*) /blocked$1 [R]");
+
+ Tomcat.addServlet(ctx, "snoop", new SnoopServlet());
+ ctx.addServletMappingDecoded("/other", "snoop");
+
+ tomcat.start();
+
+ ByteChunk res = new ByteChunk();
+ int rc = getUrl("http://localhost:" + getPort() + "/other", res,
false);
+
+ Assert.assertEquals(HttpServletResponse.SC_OK, rc);
+
+ res.setCharset(StandardCharsets.UTF_8);
+ String body = res.toString();
+ Assert.assertTrue(body, body.contains("REQUEST-URI: /other"));
+ }
}
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 1d40a6cbd4..601ae45d3b 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -346,6 +346,11 @@
Fix various instances of double decoding of URL patterns configured
either programmatically or in web.xml. (remm/markt)
</fix>
+ <fix>
+ Align the rewrite conditions <code>ornext</code> flag processing with
+ mod_rewrite, which follows a purely sequential evaluation strategy.
+ (remm)
+ </fix>
</changelog>
</subsection>
<subsection name="Coyote">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]