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 0ed01f7726 Fix BZ 66681 - NPE on batch flush when permessage-deflate enabled 0ed01f7726 is described below commit 0ed01f7726cace0804b1c9cda78687cf87953777 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 a7a9fb4524..32594c6b17 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 2f01440186..d2a420cffc 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 14f12ac999..3d7f7256a8 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -145,6 +145,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> <subsection name="Other"> <changelog> <fix> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org