This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/10.1.x by this push: new 978ff4af95 Fix BZ 66681 - NPE on batch flush when permessage-deflate enabled 978ff4af95 is described below commit 978ff4af95a78ba06208e387c6613008627f3c66 Author: Mark Thomas <ma...@apache.org> AuthorDate: Mon Jul 24 15:26:24 2023 +0100 Fix BZ 66681 - NPE on batch flush when permessage-deflate enabled https://bz.apache.org/bugzilla/show_bug.cgi?id=66681 --- .../apache/tomcat/websocket/PerMessageDeflate.java | 11 +++-- .../tomcat/websocket/TestPerMessageDeflate.java | 49 ++++++++++++++++++++++ webapps/docs/changelog.xml | 9 ++++ 3 files changed, 65 insertions(+), 4 deletions(-) diff --git a/java/org/apache/tomcat/websocket/PerMessageDeflate.java b/java/org/apache/tomcat/websocket/PerMessageDeflate.java index 665cfd24f4..6e6797d812 100644 --- a/java/org/apache/tomcat/websocket/PerMessageDeflate.java +++ b/java/org/apache/tomcat/websocket/PerMessageDeflate.java @@ -314,13 +314,16 @@ public class PerMessageDeflate implements Transformation { for (MessagePart uncompressedPart : uncompressedParts) { byte opCode = uncompressedPart.getOpCode(); - boolean emptyPart = uncompressedPart.getPayload().limit() == 0; - emptyMessage = emptyMessage && emptyPart; if (Util.isControl(opCode)) { // Control messages can appear in the middle of other messages - // and must not be compressed. Pass it straight through + // and must not be compressed. Pass it straight through. allCompressedParts.add(uncompressedPart); - } else if (emptyMessage && uncompressedPart.isFin()) { + continue; + } + + boolean emptyPart = uncompressedPart.getPayload().limit() == 0; + emptyMessage = emptyMessage && emptyPart; + if (emptyMessage && uncompressedPart.isFin()) { // Zero length messages can't be compressed so pass the // final (empty) part straight through. allCompressedParts.add(uncompressedPart); diff --git a/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java b/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java index a8301c8277..51f3b31e28 100644 --- a/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java +++ b/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java @@ -101,6 +101,55 @@ public class TestPerMessageDeflate { } + /* + * https://bz.apache.org/bugzilla/show_bug.cgi?id=66681 + */ + @Test + public void testFlushBatchMessagePart() throws IOException { + // Set up the extension using defaults + List<Parameter> parameters = Collections.emptyList(); + List<List<Parameter>> preferences = new ArrayList<>(); + preferences.add(parameters); + + // Set up the compression and sending of the message. + PerMessageDeflate perMessageDeflateTx = PerMessageDeflate.negotiate(preferences, true); + perMessageDeflateTx.setNext(new TesterTransformation()); + + List<MessagePart> uncompressedParts = new ArrayList<>(); + + // First message part + byte[] data = new byte[1024]; + ByteBuffer bb = ByteBuffer.wrap(data); + MessagePart mp1 = new MessagePart(true, 0, Constants.OPCODE_BINARY, bb, null, null, -1); + uncompressedParts.add(mp1); + + // Flush message (replicates result of calling flushBatch() + MessagePart mp2 = new MessagePart(true, 0, Constants.INTERNAL_OPCODE_FLUSH, null, null, null, -1); + uncompressedParts.add(mp2); + + List<MessagePart> compressedParts = perMessageDeflateTx.sendMessagePart(uncompressedParts); + + Assert.assertEquals(2, compressedParts.size()); + + // Check the first compressed part + MessagePart compressedPart1 = compressedParts.get(0); + + // Set up the decompression and process the received message + PerMessageDeflate perMessageDeflateRx = PerMessageDeflate.negotiate(preferences, true); + perMessageDeflateRx.setNext(new TesterTransformation(compressedPart1.getPayload())); + + ByteBuffer received = ByteBuffer.allocate(8192); + + TransformationResult tr = perMessageDeflateRx.getMoreData(compressedPart1.getOpCode(), compressedPart1.isFin(), + compressedPart1.getRsv(), received); + + Assert.assertEquals(1024, received.position()); + Assert.assertEquals(TransformationResult.END_OF_FRAME, tr); + + // Check the second compressed part (should be passed through unchanged) + Assert.assertEquals(mp2, compressedParts.get(1)); + } + /* * Minimal implementation to enable other transformations to be tested. It is NOT robust. */ diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index 3a9a5e18b7..460ea09733 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -124,6 +124,15 @@ </fix> </changelog> </subsection> + <subsection name="WebSocket"> + <changelog> + <fix> + <bug>66681</bug>: Fix a <code>NullPointerException</code> when flushing + batched messages with compression enabled using + <code>permessage-deflate</code>. (markt) + </fix> + </changelog> + </subsection> </section> <section name="Tomcat 10.1.11 (schultz)" rtext="Released 2023-07-10"> <subsection name="Catalina"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org