diff -up ./java/org/apache/catalina/websocket/LocalStrings.properties.orig ./java/org/apache/catalina/websocket/LocalStrings.properties --- ./java/org/apache/catalina/websocket/LocalStrings.properties.orig 2020-07-17 15:26:30.639711576 -0400 +++ ./java/org/apache/catalina/websocket/LocalStrings.properties 2020-07-17 15:26:39.051723026 -0400 @@ -14,6 +14,7 @@ # limitations under the License. frame.eos=The end of the stream was reached before the expected number of payload bytes could be read +frame.invalidLength=An invalid payload length was specified frame.invalidUtf8=A sequence of bytes was received that did not represent valid UTF-8 frame.readFailed=Failed to read the first byte of the next WebSocket frame. The return value from the read was [{0}] frame.readEos=The end of the stream was reached when trying to read the first byte of a new WebSocket frame diff -up ./java/org/apache/catalina/websocket/WsFrame.java.orig ./java/org/apache/catalina/websocket/WsFrame.java --- ./java/org/apache/catalina/websocket/WsFrame.java.orig 2020-07-17 15:26:44.341730227 -0400 +++ ./java/org/apache/catalina/websocket/WsFrame.java 2020-07-17 15:27:02.712755233 -0400 @@ -84,6 +84,12 @@ public class WsFrame { blockingRead(processor, extended); payloadLength = Conversions.byteArrayToLong(extended); } + // The most significant bit of those 8 bytes is required to be zero + // (see RFC 6455, section 5.2). If the most significant bit is set, + // the resulting payload length will be negative so test for that. + if (payloadLength < 0) { + throw new IOException(sm.getString("frame.invalidLength")); + } if (isControl()) { if (payloadLength > 125) { diff -up ./java/org/apache/tomcat/websocket/LocalStrings.properties.orig ./java/org/apache/tomcat/websocket/LocalStrings.properties --- ./java/org/apache/tomcat/websocket/LocalStrings.properties.orig 2020-07-17 15:25:18.940613973 -0400 +++ ./java/org/apache/tomcat/websocket/LocalStrings.properties 2020-07-17 15:25:24.954622163 -0400 @@ -63,6 +63,7 @@ wsFrame.noContinuation=A new message was wsFrame.notMasked=The client frame was not masked but all client frames must be masked wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid wsFrame.partialHeaderComplete=WebSocket frame received. fin [{0}], rsv [{1}], OpCode [{2}], payload length [{3}] +wsFrame.payloadMsbInvalid=An invalid WebSocket frame was received - the most significant bit of a 64-bit payload was illegally set wsFrame.sessionClosed=The client data cannot be processed because the session has already been closed wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages wsFrame.wrongRsv=The client frame set the reserved bits to [{0}] for a message with opCode [{1}] which was not supported by this endpoint diff -up ./java/org/apache/tomcat/websocket/WsFrameBase.java.orig ./java/org/apache/tomcat/websocket/WsFrameBase.java --- ./java/org/apache/tomcat/websocket/WsFrameBase.java.orig 2020-07-17 15:25:04.371594139 -0400 +++ ./java/org/apache/tomcat/websocket/WsFrameBase.java 2020-07-17 15:25:14.292607645 -0400 @@ -260,6 +260,13 @@ public abstract class WsFrameBase { readPos += 2; } else if (payloadLength == 127) { payloadLength = byteArrayToLong(inputBuffer, readPos, 8); + // The most significant bit of those 8 bytes is required to be zero + // (see RFC 6455, section 5.2). If the most significant bit is set, + // the resulting payload length will be negative so test for that. + if (payloadLength < 0) { + throw new WsIOException( + new CloseReason(CloseCodes.PROTOCOL_ERROR, sm.getString("wsFrame.payloadMsbInvalid"))); + } readPos += 8; } if (Util.isControl(opCode)) { diff -up ./webapps/docs/changelog.xml.orig ./webapps/docs/changelog.xml --- ./webapps/docs/changelog.xml.orig 2020-07-20 10:35:46.126504549 -0400 +++ ./webapps/docs/changelog.xml 2020-07-20 10:36:48.577591763 -0400 @@ -57,6 +57,16 @@ They eventually become mixed with the numbered issues. (I.e., numbered issues do not "pop up" wrt. others). --> +
+ + + + 64563: Add additional validation of payload length for + WebSocket messages. (markt) + + + +