You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by re...@apache.org on 2026/10/17 15:50:28 UTC
(tomcat) 09/17: Validate the WebSocket maximum message buffer size
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
commit 3bcf5f2be743d030e08cdaa22155f9397865a252
Author: opencode <re...@apache.org>
AuthorDate: Sat Oct 17 11:38:36 2026 +0200
Validate the WebSocket maximum message buffer size
The session setters setMaxBinaryMessageBufferSize() /
setMaxTextMessageBufferSize() and the container default setters
setDefaultMaxBinaryMessageBufferSize() /
setDefaultMaxTextMessageBufferSize() accepted any int without
validation.
With a zero size and a MessageHandler.Partial registered, the frame
receiver enters an unbounded busy loop: the terminal transformation
always reports OVERFLOW because the destination buffer has no room, so
the application handler is invoked repeatedly with empty buffers and
the frame payload is never consumed. A negative size results in a
NegativeArraySizeException when the message buffer is allocated.
Reject values below one with an IllegalArgumentException in the four
setters. Since the session initializes its sizes from the container
defaults and the server context init parameters are applied through the
container setters, this covers all configuration paths. Add a
regression test covering the container and session setters.
---
.../tomcat/websocket/LocalStrings.properties | 2 +
java/org/apache/tomcat/websocket/WsSession.java | 6 +++
.../tomcat/websocket/WsWebSocketContainer.java | 8 ++++
.../tomcat/websocket/TestWsWebSocketContainer.java | 47 ++++++++++++++++++++++
4 files changed, 63 insertions(+)
diff --git a/java/org/apache/tomcat/websocket/LocalStrings.properties b/java/org/apache/tomcat/websocket/LocalStrings.properties
index ca80062af0..5536b82290 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings.properties
@@ -132,6 +132,7 @@ wsSession.duplicateHandlerBinary=A binary message handler has already been confi
wsSession.duplicateHandlerPong=A pong message handler has already been configured
wsSession.duplicateHandlerText=A text message handler has already been configured
wsSession.flushFailOnClose=Failed to flush batched messages on session close
+wsSession.illegalBufferSize=Invalid maximum message buffer size [{0}]. The value must be greater than zero.
wsSession.instanceCreateFailed=Endpoint instance creation failed
wsSession.instanceNew=Endpoint instance registration failed
wsSession.invalidHandlerTypePong=A pong message handler must implement MessageHandler.Whole
@@ -155,6 +156,7 @@ wsWebSocketContainer.connect.write=Writing the HTTP upgrade request from buffer
wsWebSocketContainer.defaultConfiguratorFail=Failed to create the default configurator
wsWebSocketContainer.failedAuthentication=Failed to handle HTTP response code [{0}]. [{1}] header was not accepted by server.
wsWebSocketContainer.httpRequestFailed=The HTTP request to initiate the WebSocket connection to [{0}] failed
+wsWebSocketContainer.illegalBufferSize=Invalid default maximum message buffer size [{0}]. The value must be greater than zero.
wsWebSocketContainer.invalidExtensionsHeader=The server sent an invalid extension header
wsWebSocketContainer.invalidExtensionParameters=The server responded with extension parameters the client is unable to support
wsWebSocketContainer.invalidHeader=Unable to parse HTTP header as no colon is present to delimit header name and header value in [{0}]. The header has been skipped.
diff --git a/java/org/apache/tomcat/websocket/WsSession.java b/java/org/apache/tomcat/websocket/WsSession.java
index c8690ad44a..9f3ed1c01a 100644
--- a/java/org/apache/tomcat/websocket/WsSession.java
+++ b/java/org/apache/tomcat/websocket/WsSession.java
@@ -495,6 +495,9 @@ public class WsSession implements Session {
@Override
public void setMaxBinaryMessageBufferSize(int max) {
checkState();
+ if (max < 1) {
+ throw new IllegalArgumentException(sm.getString("wsSession.illegalBufferSize", Integer.valueOf(max)));
+ }
this.maxBinaryMessageBufferSize = max;
}
@@ -509,6 +512,9 @@ public class WsSession implements Session {
@Override
public void setMaxTextMessageBufferSize(int max) {
checkState();
+ if (max < 1) {
+ throw new IllegalArgumentException(sm.getString("wsSession.illegalBufferSize", Integer.valueOf(max)));
+ }
this.maxTextMessageBufferSize = max;
}
diff --git a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
index 212451fe4e..cda0f24783 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -1022,6 +1022,10 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce
@Override
public void setDefaultMaxBinaryMessageBufferSize(int max) {
+ if (max < 1) {
+ throw new IllegalArgumentException(
+ sm.getString("wsWebSocketContainer.illegalBufferSize", Integer.valueOf(max)));
+ }
maxBinaryMessageBufferSize = max;
}
@@ -1034,6 +1038,10 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce
@Override
public void setDefaultMaxTextMessageBufferSize(int max) {
+ if (max < 1) {
+ throw new IllegalArgumentException(
+ sm.getString("wsWebSocketContainer.illegalBufferSize", Integer.valueOf(max)));
+ }
maxTextMessageBufferSize = max;
}
diff --git a/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java b/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java
index 21e332596f..ce42d64a85 100644
--- a/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java
+++ b/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java
@@ -25,6 +25,7 @@ import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import java.util.function.IntConsumer;
import jakarta.servlet.ServletContextEvent;
import jakarta.websocket.ClientEndpointConfig;
@@ -106,6 +107,52 @@ public class TestWsWebSocketContainer extends WsWebSocketContainerBaseTest {
}
+ @Test
+ public void testMaxMessageBufferSizeValidation() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+ // No file system docBase required
+ Context ctx = getProgrammaticRootContext();
+ ctx.addApplicationListener(TesterEchoServer.Config.class.getName());
+ Tomcat.addServlet(ctx, "default", new DefaultServlet());
+ ctx.addServletMapping("/", "default");
+
+ tomcat.start();
+
+ WsWebSocketContainer wsContainer = new WsWebSocketContainer();
+
+ doTestIllegalBufferSize(wsContainer::setDefaultMaxBinaryMessageBufferSize);
+ doTestIllegalBufferSize(wsContainer::setDefaultMaxTextMessageBufferSize);
+
+ Session wsSession = wsContainer.connectToServer(TesterProgrammaticEndpoint.class,
+ ClientEndpointConfig.Builder.create().build(),
+ new URI("ws://" + getHostName() + ":" + getPort() + TesterEchoServer.Config.PATH_ASYNC));
+
+ doTestIllegalBufferSize(wsSession::setMaxBinaryMessageBufferSize);
+ doTestIllegalBufferSize(wsSession::setMaxTextMessageBufferSize);
+
+ // Positive values remain valid
+ wsSession.setMaxBinaryMessageBufferSize(1);
+ Assert.assertEquals(1, wsSession.getMaxBinaryMessageBufferSize());
+ wsSession.setMaxTextMessageBufferSize(1);
+ Assert.assertEquals(1, wsSession.getMaxTextMessageBufferSize());
+
+ wsSession.close();
+ wsContainer.destroy();
+ }
+
+
+ private static void doTestIllegalBufferSize(IntConsumer setter) {
+ for (int size : new int[] { 0, -1 }) {
+ try {
+ setter.accept(size);
+ Assert.fail("No exception thrown for buffer size [" + size + "]");
+ } catch (IllegalArgumentException iae) {
+ // Expected
+ }
+ }
+ }
+
+
@Test(expected = DeploymentException.class)
public void testConnectToServerEndpointInvalidScheme() throws Exception {
Tomcat tomcat = getTomcatInstance();
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org