[tomcat] branch main updated: Refactor. Add new method isToken(String) to reduce duplication
This is an automated email from the ASF dual-hosted git repository. markt 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 fe909ba Refactor. Add new method isToken(String) to reduce duplication fe909ba is described below commit fe909bad46150ffb9dcd436c0095ab97c20a2745 Author: Mark Thomas AuthorDate: Fri Jan 7 19:46:15 2022 + Refactor. Add new method isToken(String) to reduce duplication --- .../catalina/core/ApplicationPushBuilder.java | 7 ++--- .../tomcat/util/http/Rfc6265CookieProcessor.java | 10 ++ .../apache/tomcat/util/http/parser/HttpParser.java | 17 ++ .../tomcat/util/http/parser/TestHttpParser.java| 36 ++ webapps/docs/changelog.xml | 3 ++ 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/java/org/apache/catalina/core/ApplicationPushBuilder.java b/java/org/apache/catalina/core/ApplicationPushBuilder.java index 0b5679b..525c779 100644 --- a/java/org/apache/catalina/core/ApplicationPushBuilder.java +++ b/java/org/apache/catalina/core/ApplicationPushBuilder.java @@ -199,11 +199,8 @@ public class ApplicationPushBuilder implements PushBuilder { sm.getString("applicationPushBuilder.methodInvalid", upperMethod)); } // Check a token was supplied -for (char c : upperMethod.toCharArray()) { -if (!HttpParser.isToken(c)) { -throw new IllegalArgumentException( -sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); -} +if (!HttpParser.isToken(upperMethod)) { +throw new IllegalArgumentException(sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); } this.method = method; return this; diff --git a/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java b/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java index 79fe0d9..b7f85f5 100644 --- a/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java +++ b/java/org/apache/tomcat/util/http/Rfc6265CookieProcessor.java @@ -272,15 +272,11 @@ public class Rfc6265CookieProcessor extends CookieProcessorBase { private void validateAttribute(String name, String value) { -char[] chars = name.toCharArray(); -for (char ch : chars) { -if (!HttpParser.isToken(ch)) { -throw new IllegalArgumentException(sm.getString( -"rfc6265CookieProcessor.invalidAttributeName", name)); -} +if (!HttpParser.isToken(name)) { +throw new IllegalArgumentException(sm.getString("rfc6265CookieProcessor.invalidAttributeName", name)); } -chars = value.toCharArray(); +char[] chars = value.toCharArray(); for (char ch : chars) { if (ch < 0x20 || ch > 0x7E || ch == ';') { throw new IllegalArgumentException(sm.getString( diff --git a/java/org/apache/tomcat/util/http/parser/HttpParser.java b/java/org/apache/tomcat/util/http/parser/HttpParser.java index b06d468..7dcb631 100644 --- a/java/org/apache/tomcat/util/http/parser/HttpParser.java +++ b/java/org/apache/tomcat/util/http/parser/HttpParser.java @@ -237,6 +237,23 @@ public class HttpParser { } +public static boolean isToken(String s) { +// token = 1 * tchar (RFC 7230) +if (s == null) { +return false; +} +if (s.isEmpty()) { +return false; +} +for (char c : s.toCharArray()) { +if (!isToken(c)) { +return false; +} +} +return true; +} + + public static boolean isHex(int c) { // Fast for correct values, slower for some incorrect ones try { diff --git a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java index 6280ab6..eda10e3 100644 --- a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java +++ b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java @@ -142,4 +142,40 @@ public class TestHttpParser { String result = "ab\"ab"; Assert.assertEquals(result, HttpParser.unquote(shortText)); } + + +@Test +public void testTokenStringNull() { +Assert.assertFalse(HttpParser.isToken(null)); +} + + +@Test +public void testTokenStringEmpty() { +Assert.assertFalse(HttpParser.isToken("")); +} + + +@Test +public void testTokenStringLws01() { +Assert.assertFalse(HttpParser.isToken(" ")); +} + + +@Test +public void testTokenStringLws02() { +Assert.assertFalse(HttpParser.isToken(" aaa")); +} + + +@Test +public void testTokenStringLws03() { +Assert.assertFalse(HttpParser.isToken("\taaa")); +} + + +@Test +pub
[tomcat] branch 10.0.x updated: Refactor. Add new method isToken(String) to reduce duplication
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.0.x by this push: new 63a59f1 Refactor. Add new method isToken(String) to reduce duplication 63a59f1 is described below commit 63a59f1786d09c39067d12a3634a6b912b0b31f1 Author: Mark Thomas AuthorDate: Fri Jan 7 19:46:15 2022 + Refactor. Add new method isToken(String) to reduce duplication --- .../catalina/core/ApplicationPushBuilder.java | 7 ++--- .../apache/tomcat/util/http/parser/HttpParser.java | 17 ++ .../tomcat/util/http/parser/TestHttpParser.java| 36 ++ webapps/docs/changelog.xml | 3 ++ 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/java/org/apache/catalina/core/ApplicationPushBuilder.java b/java/org/apache/catalina/core/ApplicationPushBuilder.java index 0b5679b..525c779 100644 --- a/java/org/apache/catalina/core/ApplicationPushBuilder.java +++ b/java/org/apache/catalina/core/ApplicationPushBuilder.java @@ -199,11 +199,8 @@ public class ApplicationPushBuilder implements PushBuilder { sm.getString("applicationPushBuilder.methodInvalid", upperMethod)); } // Check a token was supplied -for (char c : upperMethod.toCharArray()) { -if (!HttpParser.isToken(c)) { -throw new IllegalArgumentException( -sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); -} +if (!HttpParser.isToken(upperMethod)) { +throw new IllegalArgumentException(sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); } this.method = method; return this; diff --git a/java/org/apache/tomcat/util/http/parser/HttpParser.java b/java/org/apache/tomcat/util/http/parser/HttpParser.java index b06d468..7dcb631 100644 --- a/java/org/apache/tomcat/util/http/parser/HttpParser.java +++ b/java/org/apache/tomcat/util/http/parser/HttpParser.java @@ -237,6 +237,23 @@ public class HttpParser { } +public static boolean isToken(String s) { +// token = 1 * tchar (RFC 7230) +if (s == null) { +return false; +} +if (s.isEmpty()) { +return false; +} +for (char c : s.toCharArray()) { +if (!isToken(c)) { +return false; +} +} +return true; +} + + public static boolean isHex(int c) { // Fast for correct values, slower for some incorrect ones try { diff --git a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java index 6280ab6..eda10e3 100644 --- a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java +++ b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java @@ -142,4 +142,40 @@ public class TestHttpParser { String result = "ab\"ab"; Assert.assertEquals(result, HttpParser.unquote(shortText)); } + + +@Test +public void testTokenStringNull() { +Assert.assertFalse(HttpParser.isToken(null)); +} + + +@Test +public void testTokenStringEmpty() { +Assert.assertFalse(HttpParser.isToken("")); +} + + +@Test +public void testTokenStringLws01() { +Assert.assertFalse(HttpParser.isToken(" ")); +} + + +@Test +public void testTokenStringLws02() { +Assert.assertFalse(HttpParser.isToken(" aaa")); +} + + +@Test +public void testTokenStringLws03() { +Assert.assertFalse(HttpParser.isToken("\taaa")); +} + + +@Test +public void testTokenStringValid() { +Assert.assertTrue(HttpParser.isToken("token")); +} } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 301a28f..962db8c 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -145,6 +145,9 @@ 65767: Add support for certificates that use keys encrypted using PBES2. Based on a pull request provided by xiezhaokun. (markt) + +Refactor testing whether a String is a valid HTTP token. (markt) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Refactor. Add new method isToken(String) to reduce duplication
This is an automated email from the ASF dual-hosted git repository. markt 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 664049a Refactor. Add new method isToken(String) to reduce duplication 664049a is described below commit 664049ad8a6b1ccda5a05a571313fa3d14875507 Author: Mark Thomas AuthorDate: Fri Jan 7 19:46:15 2022 + Refactor. Add new method isToken(String) to reduce duplication --- .../catalina/core/ApplicationPushBuilder.java | 7 ++--- .../apache/tomcat/util/http/parser/HttpParser.java | 17 ++ .../tomcat/util/http/parser/TestHttpParser.java| 36 ++ webapps/docs/changelog.xml | 3 ++ 4 files changed, 58 insertions(+), 5 deletions(-) diff --git a/java/org/apache/catalina/core/ApplicationPushBuilder.java b/java/org/apache/catalina/core/ApplicationPushBuilder.java index 805d32c..67729cf 100644 --- a/java/org/apache/catalina/core/ApplicationPushBuilder.java +++ b/java/org/apache/catalina/core/ApplicationPushBuilder.java @@ -199,11 +199,8 @@ public class ApplicationPushBuilder implements PushBuilder { sm.getString("applicationPushBuilder.methodInvalid", upperMethod)); } // Check a token was supplied -for (char c : upperMethod.toCharArray()) { -if (!HttpParser.isToken(c)) { -throw new IllegalArgumentException( -sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); -} +if (!HttpParser.isToken(upperMethod)) { +throw new IllegalArgumentException(sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); } this.method = method; return this; diff --git a/java/org/apache/tomcat/util/http/parser/HttpParser.java b/java/org/apache/tomcat/util/http/parser/HttpParser.java index b06d468..7dcb631 100644 --- a/java/org/apache/tomcat/util/http/parser/HttpParser.java +++ b/java/org/apache/tomcat/util/http/parser/HttpParser.java @@ -237,6 +237,23 @@ public class HttpParser { } +public static boolean isToken(String s) { +// token = 1 * tchar (RFC 7230) +if (s == null) { +return false; +} +if (s.isEmpty()) { +return false; +} +for (char c : s.toCharArray()) { +if (!isToken(c)) { +return false; +} +} +return true; +} + + public static boolean isHex(int c) { // Fast for correct values, slower for some incorrect ones try { diff --git a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java index 6280ab6..eda10e3 100644 --- a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java +++ b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java @@ -142,4 +142,40 @@ public class TestHttpParser { String result = "ab\"ab"; Assert.assertEquals(result, HttpParser.unquote(shortText)); } + + +@Test +public void testTokenStringNull() { +Assert.assertFalse(HttpParser.isToken(null)); +} + + +@Test +public void testTokenStringEmpty() { +Assert.assertFalse(HttpParser.isToken("")); +} + + +@Test +public void testTokenStringLws01() { +Assert.assertFalse(HttpParser.isToken(" ")); +} + + +@Test +public void testTokenStringLws02() { +Assert.assertFalse(HttpParser.isToken(" aaa")); +} + + +@Test +public void testTokenStringLws03() { +Assert.assertFalse(HttpParser.isToken("\taaa")); +} + + +@Test +public void testTokenStringValid() { +Assert.assertTrue(HttpParser.isToken("token")); +} } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 51964e7..31c1cba 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -145,6 +145,9 @@ 65767: Add support for certificates that use keys encrypted using PBES2. Based on a pull request provided by xiezhaokun. (markt) + +Refactor testing whether a String is a valid HTTP token. (markt) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Refactor. Add new method isToken(String) to reduce duplication
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/8.5.x by this push: new 744609a Refactor. Add new method isToken(String) to reduce duplication 744609a is described below commit 744609a865169b41f9c64b450e38f091fbda5f86 Author: Mark Thomas AuthorDate: Fri Jan 7 19:46:15 2022 + Refactor. Add new method isToken(String) to reduce duplication --- .../catalina/core/ApplicationPushBuilder.java | 7 ++--- .../apache/tomcat/util/http/parser/HttpParser.java | 17 +++ .../tomcat/util/http/parser/TestHttpParser.java| 34 ++ webapps/docs/changelog.xml | 3 ++ 4 files changed, 56 insertions(+), 5 deletions(-) diff --git a/java/org/apache/catalina/core/ApplicationPushBuilder.java b/java/org/apache/catalina/core/ApplicationPushBuilder.java index 6eae33f..57e62bc 100644 --- a/java/org/apache/catalina/core/ApplicationPushBuilder.java +++ b/java/org/apache/catalina/core/ApplicationPushBuilder.java @@ -203,11 +203,8 @@ public class ApplicationPushBuilder { sm.getString("applicationPushBuilder.methodInvalid", upperMethod)); } // Check a token was supplied -for (char c : upperMethod.toCharArray()) { -if (!HttpParser.isToken(c)) { -throw new IllegalArgumentException( -sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); -} +if (!HttpParser.isToken(upperMethod)) { +throw new IllegalArgumentException(sm.getString("applicationPushBuilder.methodNotToken", upperMethod)); } this.method = method; return this; diff --git a/java/org/apache/tomcat/util/http/parser/HttpParser.java b/java/org/apache/tomcat/util/http/parser/HttpParser.java index 7258955..37dcc55 100644 --- a/java/org/apache/tomcat/util/http/parser/HttpParser.java +++ b/java/org/apache/tomcat/util/http/parser/HttpParser.java @@ -257,6 +257,23 @@ public class HttpParser { } +public static boolean isToken(String s) { +// token = 1 * tchar (RFC 7230) +if (s == null) { +return false; +} +if (s.isEmpty()) { +return false; +} +for (char c : s.toCharArray()) { +if (!isToken(c)) { +return false; +} +} +return true; +} + + public static boolean isHex(int c) { // Fast for correct values, slower for some incorrect ones try { diff --git a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java index 9227e7d..d157014 100644 --- a/test/org/apache/tomcat/util/http/parser/TestHttpParser.java +++ b/test/org/apache/tomcat/util/http/parser/TestHttpParser.java @@ -25,4 +25,38 @@ public class TestHttpParser { public void testTokenDel() { Assert.assertFalse("DEL is not a token", HttpParser.isToken(127)); } +@Test +public void testTokenStringNull() { +Assert.assertFalse(HttpParser.isToken(null)); +} + + +@Test +public void testTokenStringEmpty() { +Assert.assertFalse(HttpParser.isToken("")); +} + + +@Test +public void testTokenStringLws01() { +Assert.assertFalse(HttpParser.isToken(" ")); +} + + +@Test +public void testTokenStringLws02() { +Assert.assertFalse(HttpParser.isToken(" aaa")); +} + + +@Test +public void testTokenStringLws03() { +Assert.assertFalse(HttpParser.isToken("\taaa")); +} + + +@Test +public void testTokenStringValid() { +Assert.assertTrue(HttpParser.isToken("token")); +} } diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index bc9a896..6f199f7 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -201,6 +201,9 @@ 65767: Add support for certificates that use keys encrypted using PBES2. Based on a pull request provided by xiezhaokun. (markt) + +Refactor testing whether a String is a valid HTTP token. (markt) + - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch main updated: Update h2 to avoid github security nag
This is an automated email from the ASF dual-hosted git repository. markt 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 212ca30 Update h2 to avoid github security nag 212ca30 is described below commit 212ca30334a5308aae914e43d87046e225557c4a Author: Mark Thomas AuthorDate: Fri Jan 7 19:51:29 2022 + Update h2 to avoid github security nag --- modules/jdbc-pool/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/jdbc-pool/pom.xml b/modules/jdbc-pool/pom.xml index 327b037..8366753 100644 --- a/modules/jdbc-pool/pom.xml +++ b/modules/jdbc-pool/pom.xml @@ -82,7 +82,7 @@ com.h2database h2 - 2.0.204 + 2.0.206 test - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 10.0.x updated: Update h2 to avoid github security nag
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.0.x by this push: new b3ffbb0 Update h2 to avoid github security nag b3ffbb0 is described below commit b3ffbb0c834c19c7a03ffc54c2377d4fdfcdfaa1 Author: Mark Thomas AuthorDate: Fri Jan 7 19:51:29 2022 + Update h2 to avoid github security nag --- modules/jdbc-pool/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/jdbc-pool/pom.xml b/modules/jdbc-pool/pom.xml index 1d49083..5daf760 100644 --- a/modules/jdbc-pool/pom.xml +++ b/modules/jdbc-pool/pom.xml @@ -82,7 +82,7 @@ com.h2database h2 - 2.0.204 + 2.0.206 test - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Update h2 to avoid github security nag
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/8.5.x by this push: new 3f1eaa7 Update h2 to avoid github security nag 3f1eaa7 is described below commit 3f1eaa7d51d7b8bf519613b6cd0d70a4cec2 Author: Mark Thomas AuthorDate: Fri Jan 7 19:51:29 2022 + Update h2 to avoid github security nag --- modules/jdbc-pool/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/jdbc-pool/pom.xml b/modules/jdbc-pool/pom.xml index bb05975..7a32f8a 100644 --- a/modules/jdbc-pool/pom.xml +++ b/modules/jdbc-pool/pom.xml @@ -80,7 +80,7 @@ com.h2database h2 - 2.0.204 + 2.0.206 test - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Update h2 to avoid github security nag
This is an automated email from the ASF dual-hosted git repository. markt 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 7e6cf54 Update h2 to avoid github security nag 7e6cf54 is described below commit 7e6cf54d38a96c676a94e2784272adbd502c8142 Author: Mark Thomas AuthorDate: Fri Jan 7 19:51:29 2022 + Update h2 to avoid github security nag --- modules/jdbc-pool/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/jdbc-pool/pom.xml b/modules/jdbc-pool/pom.xml index ad0cb18..58a1425 100644 --- a/modules/jdbc-pool/pom.xml +++ b/modules/jdbc-pool/pom.xml @@ -82,7 +82,7 @@ com.h2database h2 - 2.0.204 + 2.0.206 test - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[GitHub] [tomcat] michael-o commented on pull request #428: Enhancement: Additional user attributes queried by (some) realms
michael-o commented on pull request #428: URL: https://github.com/apache/tomcat/pull/428#issuecomment-1007732098 @cklein05 Can you rebase? -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch main updated: Fix BZ 65785 - additional HTTP/2 header validation
This is an automated email from the ASF dual-hosted git repository. markt 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 d909c70 Fix BZ 65785 - additional HTTP/2 header validation d909c70 is described below commit d909c709b639e9670edce2581293afb9626d7b5e Author: Mark Thomas AuthorDate: Fri Jan 7 22:43:03 2022 + Fix BZ 65785 - additional HTTP/2 header validation https://bz.apache.org/bugzilla/show_bug.cgi?id=65785 --- java/org/apache/coyote/http2/StreamProcessor.java | 70 +++- .../apache/coyote/http2/TestStreamProcessor.java | 177 + webapps/docs/changelog.xml | 4 + 3 files changed, 250 insertions(+), 1 deletion(-) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index bbaf902..c1a943a 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -18,9 +18,11 @@ package org.apache.coyote.http2; import java.io.File; import java.io.IOException; +import java.util.Enumeration; import java.util.Iterator; import jakarta.servlet.ServletConnection; +import jakarta.servlet.http.HttpServletResponse; import org.apache.coyote.AbstractProcessor; import org.apache.coyote.ActionCode; @@ -37,6 +39,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.MimeHeaders; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.net.DispatchType; import org.apache.tomcat.util.net.SendfileState; @@ -412,7 +415,13 @@ class StreamProcessor extends AbstractProcessor { @Override public final SocketState service(SocketWrapperBase socket) throws IOException { try { -adapter.service(request, response); +if (validateRequest()) { +adapter.service(request, response); +} else { +response.setStatus(HttpServletResponse.SC_BAD_REQUEST); +adapter.log(request, response, 0); +setErrorState(ErrorState.CLOSE_CLEAN, null); +} } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(sm.getString("streamProcessor.service.error"), e); @@ -437,6 +446,65 @@ class StreamProcessor extends AbstractProcessor { } +/* + * In HTTP/1.1 some aspects of the request are validated as the request is + * parsed and the request rejected immediately with a 400 response. These + * checks are performed in Http11InputBuffer. Because, in Tomcat's HTTP/2 + * implementation, incoming frames are processed on one thread while the + * corresponding request/response is processed on a separate thread, + * rejecting invalid requests is more involved. + * + * One approach would be to validate the request during parsing, note any + * validation errors and then generate a 400 response once processing moves + * to the separate request/response thread. This would require refactoring + * to track the validation errors. + * + * A second approach, and the one currently adopted, is to perform the + * validation shortly after processing of the received request passes to the + * separate thread and to generate a 400 response if validation fails. + * + * The checks performed below are based on the checks in Http11InputBuffer. + */ +private boolean validateRequest() { +// Method name must be a token +String method = request.method().toString(); +if (!HttpParser.isToken(method)) { +return false; +} + +// Invalid character in request target +// (other checks such as valid %nn happen later) +ByteChunk bc = request.requestURI().getByteChunk(); +for (int i = bc.getStart(); i < bc.getEnd(); i++) { +if (HttpParser.isNotRequestTarget(bc.getBuffer()[i])) { +return false; +} +} + +// Ensure the query string doesn't contain invalid characters. +// (other checks such as valid %nn happen later) +String qs = request.queryString().toString(); +if (qs != null) { +for (char c : qs.toCharArray()) { +if (!HttpParser.isQuery(c)) { +return false; +} +} +} + +// HTTP header names must be tokens. +MimeHeaders headers = request.getMimeHeaders(); +Enumeration names = headers.names(); +while (names.hasMoreElements()) { +if (!HttpParser.isToken(names.nextElement())) { +return false; +} +
[tomcat] branch 10.0.x updated: Fix BZ 65785 - additional HTTP/2 header validation
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.0.x by this push: new c387ee6 Fix BZ 65785 - additional HTTP/2 header validation c387ee6 is described below commit c387ee6917abe1a787510aef2139b8b36df36698 Author: Mark Thomas AuthorDate: Fri Jan 7 22:43:03 2022 + Fix BZ 65785 - additional HTTP/2 header validation https://bz.apache.org/bugzilla/show_bug.cgi?id=65785 --- java/org/apache/coyote/http2/StreamProcessor.java | 71 - .../apache/coyote/http2/TestStreamProcessor.java | 177 + webapps/docs/changelog.xml | 4 + 3 files changed, 251 insertions(+), 1 deletion(-) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index d1ae2f9..df0eb7f 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -18,8 +18,11 @@ package org.apache.coyote.http2; import java.io.File; import java.io.IOException; +import java.util.Enumeration; import java.util.Iterator; +import jakarta.servlet.http.HttpServletResponse; + import org.apache.coyote.AbstractProcessor; import org.apache.coyote.ActionCode; import org.apache.coyote.Adapter; @@ -35,6 +38,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.MimeHeaders; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.net.DispatchType; import org.apache.tomcat.util.net.SendfileState; @@ -410,7 +414,13 @@ class StreamProcessor extends AbstractProcessor { @Override public final SocketState service(SocketWrapperBase socket) throws IOException { try { -adapter.service(request, response); +if (validateRequest()) { +adapter.service(request, response); +} else { +response.setStatus(HttpServletResponse.SC_BAD_REQUEST); +adapter.log(request, response, 0); +setErrorState(ErrorState.CLOSE_CLEAN, null); +} } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(sm.getString("streamProcessor.service.error"), e); @@ -435,6 +445,65 @@ class StreamProcessor extends AbstractProcessor { } +/* + * In HTTP/1.1 some aspects of the request are validated as the request is + * parsed and the request rejected immediately with a 400 response. These + * checks are performed in Http11InputBuffer. Because, in Tomcat's HTTP/2 + * implementation, incoming frames are processed on one thread while the + * corresponding request/response is processed on a separate thread, + * rejecting invalid requests is more involved. + * + * One approach would be to validate the request during parsing, note any + * validation errors and then generate a 400 response once processing moves + * to the separate request/response thread. This would require refactoring + * to track the validation errors. + * + * A second approach, and the one currently adopted, is to perform the + * validation shortly after processing of the received request passes to the + * separate thread and to generate a 400 response if validation fails. + * + * The checks performed below are based on the checks in Http11InputBuffer. + */ +private boolean validateRequest() { +// Method name must be a token +String method = request.method().toString(); +if (!HttpParser.isToken(method)) { +return false; +} + +// Invalid character in request target +// (other checks such as valid %nn happen later) +ByteChunk bc = request.requestURI().getByteChunk(); +for (int i = bc.getStart(); i < bc.getEnd(); i++) { +if (HttpParser.isNotRequestTarget(bc.getBuffer()[i])) { +return false; +} +} + +// Ensure the query string doesn't contain invalid characters. +// (other checks such as valid %nn happen later) +String qs = request.queryString().toString(); +if (qs != null) { +for (char c : qs.toCharArray()) { +if (!HttpParser.isQuery(c)) { +return false; +} +} +} + +// HTTP header names must be tokens. +MimeHeaders headers = request.getMimeHeaders(); +Enumeration names = headers.names(); +while (names.hasMoreElements()) { +if (!HttpParser.isToken(names.nextElement())) { +return false; +} +
[tomcat] branch 9.0.x updated: Fix BZ 65785 - additional HTTP/2 header validation
This is an automated email from the ASF dual-hosted git repository. markt 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 c652ffc Fix BZ 65785 - additional HTTP/2 header validation c652ffc is described below commit c652ffcb4e6ed965c007f8c24a2a967034e0e850 Author: Mark Thomas AuthorDate: Fri Jan 7 22:43:03 2022 + Fix BZ 65785 - additional HTTP/2 header validation https://bz.apache.org/bugzilla/show_bug.cgi?id=65785 --- java/org/apache/coyote/http2/StreamProcessor.java | 71 - .../apache/coyote/http2/TestStreamProcessor.java | 177 + webapps/docs/changelog.xml | 4 + 3 files changed, 251 insertions(+), 1 deletion(-) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index d1ae2f9..df0eb7f 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -18,8 +18,11 @@ package org.apache.coyote.http2; import java.io.File; import java.io.IOException; +import java.util.Enumeration; import java.util.Iterator; +import jakarta.servlet.http.HttpServletResponse; + import org.apache.coyote.AbstractProcessor; import org.apache.coyote.ActionCode; import org.apache.coyote.Adapter; @@ -35,6 +38,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.MimeHeaders; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.net.DispatchType; import org.apache.tomcat.util.net.SendfileState; @@ -410,7 +414,13 @@ class StreamProcessor extends AbstractProcessor { @Override public final SocketState service(SocketWrapperBase socket) throws IOException { try { -adapter.service(request, response); +if (validateRequest()) { +adapter.service(request, response); +} else { +response.setStatus(HttpServletResponse.SC_BAD_REQUEST); +adapter.log(request, response, 0); +setErrorState(ErrorState.CLOSE_CLEAN, null); +} } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(sm.getString("streamProcessor.service.error"), e); @@ -435,6 +445,65 @@ class StreamProcessor extends AbstractProcessor { } +/* + * In HTTP/1.1 some aspects of the request are validated as the request is + * parsed and the request rejected immediately with a 400 response. These + * checks are performed in Http11InputBuffer. Because, in Tomcat's HTTP/2 + * implementation, incoming frames are processed on one thread while the + * corresponding request/response is processed on a separate thread, + * rejecting invalid requests is more involved. + * + * One approach would be to validate the request during parsing, note any + * validation errors and then generate a 400 response once processing moves + * to the separate request/response thread. This would require refactoring + * to track the validation errors. + * + * A second approach, and the one currently adopted, is to perform the + * validation shortly after processing of the received request passes to the + * separate thread and to generate a 400 response if validation fails. + * + * The checks performed below are based on the checks in Http11InputBuffer. + */ +private boolean validateRequest() { +// Method name must be a token +String method = request.method().toString(); +if (!HttpParser.isToken(method)) { +return false; +} + +// Invalid character in request target +// (other checks such as valid %nn happen later) +ByteChunk bc = request.requestURI().getByteChunk(); +for (int i = bc.getStart(); i < bc.getEnd(); i++) { +if (HttpParser.isNotRequestTarget(bc.getBuffer()[i])) { +return false; +} +} + +// Ensure the query string doesn't contain invalid characters. +// (other checks such as valid %nn happen later) +String qs = request.queryString().toString(); +if (qs != null) { +for (char c : qs.toCharArray()) { +if (!HttpParser.isQuery(c)) { +return false; +} +} +} + +// HTTP header names must be tokens. +MimeHeaders headers = request.getMimeHeaders(); +Enumeration names = headers.names(); +while (names.hasMoreElements()) { +if (!HttpParser.isToken(names.nextElement())) { +return false; +} +}
[tomcat] branch 8.5.x updated: Fix BZ 65785 - additional HTTP/2 header validation
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/8.5.x by this push: new 7212b3b Fix BZ 65785 - additional HTTP/2 header validation 7212b3b is described below commit 7212b3b10dd48f83d1b4c29265751874e02b7476 Author: Mark Thomas AuthorDate: Fri Jan 7 22:43:03 2022 + Fix BZ 65785 - additional HTTP/2 header validation https://bz.apache.org/bugzilla/show_bug.cgi?id=65785 --- java/org/apache/coyote/http2/StreamProcessor.java | 71 - .../apache/coyote/http2/TestStreamProcessor.java | 177 + webapps/docs/changelog.xml | 4 + 3 files changed, 251 insertions(+), 1 deletion(-) diff --git a/java/org/apache/coyote/http2/StreamProcessor.java b/java/org/apache/coyote/http2/StreamProcessor.java index 95af082..4d1e41c 100644 --- a/java/org/apache/coyote/http2/StreamProcessor.java +++ b/java/org/apache/coyote/http2/StreamProcessor.java @@ -17,8 +17,11 @@ package org.apache.coyote.http2; import java.io.IOException; +import java.util.Enumeration; import java.util.Iterator; +import jakarta.servlet.http.HttpServletResponse; + import org.apache.coyote.AbstractProcessor; import org.apache.coyote.ActionCode; import org.apache.coyote.Adapter; @@ -34,6 +37,7 @@ import org.apache.juli.logging.LogFactory; import org.apache.tomcat.util.buf.ByteChunk; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.MimeHeaders; +import org.apache.tomcat.util.http.parser.HttpParser; import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState; import org.apache.tomcat.util.net.DispatchType; import org.apache.tomcat.util.net.SocketEvent; @@ -373,7 +377,13 @@ class StreamProcessor extends AbstractProcessor { @Override public final SocketState service(SocketWrapperBase socket) throws IOException { try { -adapter.service(request, response); +if (validateRequest()) { +adapter.service(request, response); +} else { +response.setStatus(HttpServletResponse.SC_BAD_REQUEST); +adapter.log(request, response, 0); +setErrorState(ErrorState.CLOSE_CLEAN, null); +} } catch (Exception e) { if (log.isDebugEnabled()) { log.debug(sm.getString("streamProcessor.service.error"), e); @@ -396,6 +406,65 @@ class StreamProcessor extends AbstractProcessor { } +/* + * In HTTP/1.1 some aspects of the request are validated as the request is + * parsed and the request rejected immediately with a 400 response. These + * checks are performed in Http11InputBuffer. Because, in Tomcat's HTTP/2 + * implementation, incoming frames are processed on one thread while the + * corresponding request/response is processed on a separate thread, + * rejecting invalid requests is more involved. + * + * One approach would be to validate the request during parsing, note any + * validation errors and then generate a 400 response once processing moves + * to the separate request/response thread. This would require refactoring + * to track the validation errors. + * + * A second approach, and the one currently adopted, is to perform the + * validation shortly after processing of the received request passes to the + * separate thread and to generate a 400 response if validation fails. + * + * The checks performed below are based on the checks in Http11InputBuffer. + */ +private boolean validateRequest() { +// Method name must be a token +String method = request.method().toString(); +if (!HttpParser.isToken(method)) { +return false; +} + +// Invalid character in request target +// (other checks such as valid %nn happen later) +ByteChunk bc = request.requestURI().getByteChunk(); +for (int i = bc.getStart(); i < bc.getEnd(); i++) { +if (HttpParser.isNotRequestTarget(bc.getBuffer()[i])) { +return false; +} +} + +// Ensure the query string doesn't contain invalid characters. +// (other checks such as valid %nn happen later) +String qs = request.queryString().toString(); +if (qs != null) { +for (char c : qs.toCharArray()) { +if (!HttpParser.isQuery(c)) { +return false; +} +} +} + +// HTTP header names must be tokens. +MimeHeaders headers = request.getMimeHeaders(); +Enumeration names = headers.names(); +while (names.hasMoreElements()) { +if (!HttpParser.isToken(names.nextElement())) { +return false; +} +} + +return true
[Bug 65785] HTTP/2.0 non US-ASCII header names should be rejected
https://bz.apache.org/bugzilla/show_bug.cgi?id=65785 Mark Thomas changed: What|Removed |Added Status|NEW |RESOLVED Resolution|--- |FIXED --- Comment #1 from Mark Thomas --- Fixed in: - 10.1.x for 10.1.0-M9 onwards - 10.0.x for 10.0.15 onwards - 9.0.x for 9.0.57 onwards - 8.5.x for 8.5.74 onwards -- You are receiving this mail because: You are the assignee for the bug. - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch main updated: Follow-up to fix for 65763.
This is an automated email from the ASF dual-hosted git repository. markt 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 bc56464 Follow-up to fix for 65763. bc56464 is described below commit bc564641b782a27bcf0042e453e9f4ccf44b02ea Author: Mark Thomas AuthorDate: Fri Jan 7 23:24:09 2022 + Follow-up to fix for 65763. Improving the handling of timeouts meant that code that was previously skipped due to an uncaught exception was no longer skipped and that broke some tests. Ensure close message and/or notifications are only sent once. --- java/org/apache/tomcat/websocket/WsSession.java | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/java/org/apache/tomcat/websocket/WsSession.java b/java/org/apache/tomcat/websocket/WsSession.java index 91201d2..c7e3319 100644 --- a/java/org/apache/tomcat/websocket/WsSession.java +++ b/java/org/apache/tomcat/websocket/WsSession.java @@ -598,6 +598,8 @@ public class WsSession implements Session { if (log.isDebugEnabled()) { log.debug(sm.getString("wsSession.doClose", id)); } + +// This will trigger a flush of any batched messages. try { wsRemoteEndpoint.setBatchingAllowed(false); } catch (IOException e) { @@ -605,13 +607,20 @@ public class WsSession implements Session { fireEndpointOnError(e); } -state = State.OUTPUT_CLOSED; +/* + * If the flush above fails the error handling could call this + * method recursively. Without this check, the close message and + * notifications could be sent multiple times. + */ +if (state != State.OUTPUT_CLOSED) { +state = State.OUTPUT_CLOSED; -sendCloseMessage(closeReasonMessage); -if (closeSocket) { -wsRemoteEndpoint.close(); +sendCloseMessage(closeReasonMessage); +if (closeSocket) { +wsRemoteEndpoint.close(); +} +fireEndpointOnClose(closeReasonLocal); } -fireEndpointOnClose(closeReasonLocal); } IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 10.0.x updated: Follow-up to fix for 65763.
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/10.0.x by this push: new 180c955 Follow-up to fix for 65763. 180c955 is described below commit 180c955218eea4eda7e7281047ee5120ce772974 Author: Mark Thomas AuthorDate: Fri Jan 7 23:24:09 2022 + Follow-up to fix for 65763. Improving the handling of timeouts meant that code that was previously skipped due to an uncaught exception was no longer skipped and that broke some tests. Ensure close message and/or notifications are only sent once. --- java/org/apache/tomcat/websocket/WsSession.java | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/java/org/apache/tomcat/websocket/WsSession.java b/java/org/apache/tomcat/websocket/WsSession.java index a2e8768..8766d46 100644 --- a/java/org/apache/tomcat/websocket/WsSession.java +++ b/java/org/apache/tomcat/websocket/WsSession.java @@ -692,6 +692,8 @@ public class WsSession implements Session { if (log.isDebugEnabled()) { log.debug(sm.getString("wsSession.doClose", id)); } + +// This will trigger a flush of any batched messages. try { wsRemoteEndpoint.setBatchingAllowed(false); } catch (IOException e) { @@ -699,13 +701,20 @@ public class WsSession implements Session { fireEndpointOnError(e); } -state = State.OUTPUT_CLOSED; +/* + * If the flush above fails the error handling could call this + * method recursively. Without this check, the close message and + * notifications could be sent multiple times. + */ +if (state != State.OUTPUT_CLOSED) { +state = State.OUTPUT_CLOSED; -sendCloseMessage(closeReasonMessage); -if (closeSocket) { -wsRemoteEndpoint.close(); +sendCloseMessage(closeReasonMessage); +if (closeSocket) { +wsRemoteEndpoint.close(); +} +fireEndpointOnClose(closeReasonLocal); } -fireEndpointOnClose(closeReasonLocal); } IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 9.0.x updated: Follow-up to fix for 65763.
This is an automated email from the ASF dual-hosted git repository. markt 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 9809405 Follow-up to fix for 65763. 9809405 is described below commit 98094058303f486a3533dabb7b1c26cb4113ab90 Author: Mark Thomas AuthorDate: Fri Jan 7 23:24:09 2022 + Follow-up to fix for 65763. Improving the handling of timeouts meant that code that was previously skipped due to an uncaught exception was no longer skipped and that broke some tests. Ensure close message and/or notifications are only sent once. --- java/org/apache/tomcat/websocket/WsSession.java | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/java/org/apache/tomcat/websocket/WsSession.java b/java/org/apache/tomcat/websocket/WsSession.java index dc952c1..2234fb0 100644 --- a/java/org/apache/tomcat/websocket/WsSession.java +++ b/java/org/apache/tomcat/websocket/WsSession.java @@ -691,6 +691,8 @@ public class WsSession implements Session { if (log.isDebugEnabled()) { log.debug(sm.getString("wsSession.doClose", id)); } + +// This will trigger a flush of any batched messages. try { wsRemoteEndpoint.setBatchingAllowed(false); } catch (IOException e) { @@ -698,13 +700,20 @@ public class WsSession implements Session { fireEndpointOnError(e); } -state = State.OUTPUT_CLOSED; +/* + * If the flush above fails the error handling could call this + * method recursively. Without this check, the close message and + * notifications could be sent multiple times. + */ +if (state != State.OUTPUT_CLOSED) { +state = State.OUTPUT_CLOSED; -sendCloseMessage(closeReasonMessage); -if (closeSocket) { -wsRemoteEndpoint.close(); +sendCloseMessage(closeReasonMessage); +if (closeSocket) { +wsRemoteEndpoint.close(); +} +fireEndpointOnClose(closeReasonLocal); } -fireEndpointOnClose(closeReasonLocal); } IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org
[tomcat] branch 8.5.x updated: Follow-up to fix for 65763.
This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git The following commit(s) were added to refs/heads/8.5.x by this push: new cacd49a Follow-up to fix for 65763. cacd49a is described below commit cacd49a38701bdab49444047990dc05d52edcc3a Author: Mark Thomas AuthorDate: Fri Jan 7 23:24:09 2022 + Follow-up to fix for 65763. Improving the handling of timeouts meant that code that was previously skipped due to an uncaught exception was no longer skipped and that broke some tests. Ensure close message and/or notifications are only sent once. --- java/org/apache/tomcat/websocket/WsSession.java | 19 ++- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/java/org/apache/tomcat/websocket/WsSession.java b/java/org/apache/tomcat/websocket/WsSession.java index dc952c1..2234fb0 100644 --- a/java/org/apache/tomcat/websocket/WsSession.java +++ b/java/org/apache/tomcat/websocket/WsSession.java @@ -691,6 +691,8 @@ public class WsSession implements Session { if (log.isDebugEnabled()) { log.debug(sm.getString("wsSession.doClose", id)); } + +// This will trigger a flush of any batched messages. try { wsRemoteEndpoint.setBatchingAllowed(false); } catch (IOException e) { @@ -698,13 +700,20 @@ public class WsSession implements Session { fireEndpointOnError(e); } -state = State.OUTPUT_CLOSED; +/* + * If the flush above fails the error handling could call this + * method recursively. Without this check, the close message and + * notifications could be sent multiple times. + */ +if (state != State.OUTPUT_CLOSED) { +state = State.OUTPUT_CLOSED; -sendCloseMessage(closeReasonMessage); -if (closeSocket) { -wsRemoteEndpoint.close(); +sendCloseMessage(closeReasonMessage); +if (closeSocket) { +wsRemoteEndpoint.close(); +} +fireEndpointOnClose(closeReasonLocal); } -fireEndpointOnClose(closeReasonLocal); } IOException ioe = new IOException(sm.getString("wsSession.messageFailed")); - To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org