This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 9.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit f31d971ad48de742f6a4876704f47f2c5e70756c
Author: opencode <[email protected]>
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 6cfbc6934d..91fea99600 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings.properties
@@ -123,6 +123,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
@@ -143,6 +144,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.invalidExtensionParameters=The server responded with 
extension parameters the client is unable to support
 wsWebSocketContainer.invalidExtensionsHeader=The server sent an invalid 
extension header
 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 46150e19bf..badef72406 100644
--- a/java/org/apache/tomcat/websocket/WsSession.java
+++ b/java/org/apache/tomcat/websocket/WsSession.java
@@ -589,6 +589,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;
     }
 
@@ -603,6 +606,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 eedc77a7d4..842c8aa1cc 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -1040,6 +1040,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;
     }
 
@@ -1052,6 +1056,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 1b57ce8fb3..8593fa55b2 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 javax.servlet.ServletContextEvent;
 import javax.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: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to