This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 11.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/11.0.x by this push:
new 85ceb0e87b Align encodedSolidusHandling with servlet spec
85ceb0e87b is described below
commit 85ceb0e87b39f5b6d9efc357b47f1112be2c7d12
Author: Mark Thomas <[email protected]>
AuthorDate: Mon Nov 11 15:01:00 2024 +0000
Align encodedSolidusHandling with servlet spec
---
java/org/apache/tomcat/util/buf/UDecoder.java | 17 +++++++++
test/org/apache/tomcat/util/buf/TestUDecoder.java | 42 +++++++++++++++++++++++
webapps/docs/config/ajp.xml | 9 ++++-
webapps/docs/config/http.xml | 9 ++++-
4 files changed, 75 insertions(+), 2 deletions(-)
diff --git a/java/org/apache/tomcat/util/buf/UDecoder.java
b/java/org/apache/tomcat/util/buf/UDecoder.java
index d698c5f935..b11965095e 100644
--- a/java/org/apache/tomcat/util/buf/UDecoder.java
+++ b/java/org/apache/tomcat/util/buf/UDecoder.java
@@ -145,6 +145,23 @@ public final class UDecoder {
buff[idx] = buff[j];
}
}
+ } else if (res == '%') {
+ /*
+ * If encoded '/' is going to be left encoded then so must
encoded '%' else the subsequent %nn
+ * decoding will either fail or corrupt the output.
+ */
+ switch (encodedSolidusHandling) {
+ case DECODE:
+ case REJECT: {
+ buff[idx] = (byte) res;
+ break;
+ }
+ case PASS_THROUGH: {
+ buff[idx++] = buff[j - 2];
+ buff[idx++] = buff[j - 1];
+ buff[idx] = buff[j];
+ }
+ }
} else {
buff[idx] = (byte) res;
}
diff --git a/test/org/apache/tomcat/util/buf/TestUDecoder.java
b/test/org/apache/tomcat/util/buf/TestUDecoder.java
index b2ca73dd16..94dbd14fb6 100644
--- a/test/org/apache/tomcat/util/buf/TestUDecoder.java
+++ b/test/org/apache/tomcat/util/buf/TestUDecoder.java
@@ -219,6 +219,48 @@ public class TestUDecoder {
}
+ @Test
+ public void testURLDecodeStringSolidus10a() throws IOException {
+ String result = doTestSolidus("xx%25xx",
EncodedSolidusHandling.REJECT);
+ Assert.assertEquals("xx%xx", result);
+ }
+
+
+ @Test
+ public void testURLDecodeStringSolidus10b() throws IOException {
+ String result = doTestSolidus("xx%25xx",
EncodedSolidusHandling.PASS_THROUGH);
+ Assert.assertEquals("xx%25xx", result);
+ }
+
+
+ @Test
+ public void testURLDecodeStringSolidus10c() throws IOException {
+ String result = doTestSolidus("xx%25xx",
EncodedSolidusHandling.DECODE);
+ Assert.assertEquals("xx%xx", result);
+ }
+
+
+ @Test(expected = CharConversionException.class)
+ public void testURLDecodeStringSolidus11a() throws IOException {
+ String result = doTestSolidus("xx%2f%25xx",
EncodedSolidusHandling.REJECT);
+ Assert.assertEquals("xx%xx", result);
+ }
+
+
+ @Test
+ public void testURLDecodeStringSolidus11b() throws IOException {
+ String result = doTestSolidus("xx%2f%25xx",
EncodedSolidusHandling.PASS_THROUGH);
+ Assert.assertEquals("xx%2f%25xx", result);
+ }
+
+
+ @Test
+ public void testURLDecodeStringSolidus11c() throws IOException {
+ String result = doTestSolidus("xx%2f%25xx",
EncodedSolidusHandling.DECODE);
+ Assert.assertEquals("xx/%xx", result);
+ }
+
+
private void doTestSolidus(String input, String expected) throws
IOException {
for (EncodedSolidusHandling solidusHandling :
EncodedSolidusHandling.values()) {
String result = doTestSolidus(input, solidusHandling);
diff --git a/webapps/docs/config/ajp.xml b/webapps/docs/config/ajp.xml
index 605ac3bf98..32bdcfa142 100644
--- a/webapps/docs/config/ajp.xml
+++ b/webapps/docs/config/ajp.xml
@@ -127,7 +127,14 @@
time other <code>%nn</code> sequences are decoded. When set to
<code>passthrough</code> request paths containing a <code>%2f</code>
sequence will be processed with the <code>%2f</code> sequence unchanged.
- If not specified the default value is <code>reject</code>.</p>
+ </p>
+ <p>If <code>passthrough</code> is used then it is the application's
+ resposibility to perform any further <code>%nn</code> decoding required.
+ Any <code>%25</code> sequences (encoded <code>%</code>) in the request
+ path with also be processed with the <code>%25</code> sequence unchanged
+ to avoid potential corruption and/or decoding failure when the path is
+ subsequently <code>%nn</code> decoded by the application.</p>
+ <p>If not specified the default value is <code>reject</code>.</p>
</attribute>
<attribute name="enforceEncodingInGetWriter" required="false">
diff --git a/webapps/docs/config/http.xml b/webapps/docs/config/http.xml
index b7c9d539d1..dcea9d3b40 100644
--- a/webapps/docs/config/http.xml
+++ b/webapps/docs/config/http.xml
@@ -123,7 +123,14 @@
time other <code>%nn</code> sequences are decoded. When set to
<code>passthrough</code> request paths containing a <code>%2f</code>
sequence will be processed with the <code>%2f</code> sequence unchanged.
- If not specified the default value is <code>reject</code>.</p>
+ </p>
+ <p>If <code>passthrough</code> is used then it is the application's
+ resposibility to perform any further <code>%nn</code> decoding required.
+ Any <code>%25</code> sequences (encoded <code>%</code>) in the request
+ path with also be processed with the <code>%25</code> sequence unchanged
+ to avoid potential corruption and/or decoding failure when the path is
+ subsequently <code>%nn</code> decoded by the application.</p>
+ <p>If not specified the default value is <code>reject</code>.</p>
</attribute>
<attribute name="enforceEncodingInGetWriter" required="false">
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]