This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push: new 3e1a392 Fix BZ 65317. Fix permessage-deflate with payloads of n*8192 bytes 3e1a392 is described below commit 3e1a3928486ce4e39186330c54abbb44d9d5c690 Author: Mark Thomas <ma...@apache.org> AuthorDate: Fri May 21 11:44:00 2021 +0100 Fix BZ 65317. Fix permessage-deflate with payloads of n*8192 bytes Based on a patch provided by Saksham Verma. https://bz.apache.org/bugzilla/show_bug.cgi?id=65317 --- .../apache/tomcat/websocket/PerMessageDeflate.java | 15 +++--- .../tomcat/websocket/TestPerMessageDeflate.java | 61 +++++++++++++++++++++- webapps/docs/changelog.xml | 10 ++++ 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/java/org/apache/tomcat/websocket/PerMessageDeflate.java b/java/org/apache/tomcat/websocket/PerMessageDeflate.java index afcfcf0..7fae225 100644 --- a/java/org/apache/tomcat/websocket/PerMessageDeflate.java +++ b/java/org/apache/tomcat/websocket/PerMessageDeflate.java @@ -197,7 +197,7 @@ public class PerMessageDeflate implements Transformation { int written; boolean usedEomBytes = false; - while (dest.remaining() > 0) { + while (dest.remaining() > 0 || usedEomBytes) { // Space available in destination. Try and fill it. try { written = inflater.inflate( @@ -210,12 +210,10 @@ public class PerMessageDeflate implements Transformation { dest.position(dest.position() + written); if (inflater.needsInput() && !usedEomBytes ) { + readBuffer.clear(); + TransformationResult nextResult = next.getMoreData(opCode, fin, (rsv ^ RSV_BITMASK), readBuffer); + inflater.setInput(readBuffer.array(), readBuffer.arrayOffset(), readBuffer.position()); if (dest.hasRemaining()) { - readBuffer.clear(); - TransformationResult nextResult = - next.getMoreData(opCode, fin, (rsv ^ RSV_BITMASK), readBuffer); - inflater.setInput( - readBuffer.array(), readBuffer.arrayOffset(), readBuffer.position()); if (TransformationResult.UNDERFLOW.equals(nextResult)) { return nextResult; } else if (TransformationResult.END_OF_FRAME.equals(nextResult) && @@ -227,6 +225,11 @@ public class PerMessageDeflate implements Transformation { return TransformationResult.END_OF_FRAME; } } + } else if (readBuffer.position() > 0) { + return TransformationResult.OVERFLOW; + } else if (fin) { + inflater.setInput(EOM_BYTES); + usedEomBytes = true; } } else if (written == 0) { if (fin && (isServer && !clientContextTakeover || diff --git a/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java b/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java index 9139460..4538eba 100644 --- a/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java +++ b/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java @@ -26,6 +26,7 @@ import java.util.List; import javax.websocket.Extension; import javax.websocket.Extension.Parameter; +import org.junit.Assert; import org.junit.Test; public class TestPerMessageDeflate { @@ -61,9 +62,61 @@ public class TestPerMessageDeflate { /* - * Minimal implementation to enable other transformations to be tested. + * https://bz.apache.org/bugzilla/show_bug.cgi?id=65317 + */ + @Test + public void testMessagePartThatFillsBufffer() 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()); + + byte[] data = new byte[8192]; + + ByteBuffer bb = ByteBuffer.wrap(data); + MessagePart mp = new MessagePart(true, 0, Constants.OPCODE_BINARY, bb, null, null, -1); + + List<MessagePart> uncompressedParts = new ArrayList<>(); + uncompressedParts.add(mp); + List<MessagePart> compressedParts = perMessageDeflateTx.sendMessagePart(uncompressedParts); + + MessagePart compressedPart = compressedParts.get(0); + + // Set up the decompression and process the received messafe + PerMessageDeflate perMessageDeflateRx = PerMessageDeflate.negotiate(preferences, true); + perMessageDeflateRx.setNext(new TesterTransformation(compressedPart.getPayload())); + + ByteBuffer received = ByteBuffer.allocate(8192); + + TransformationResult tr = perMessageDeflateRx.getMoreData( + compressedPart.getOpCode(), compressedPart.isFin(), compressedPart.getRsv(), received); + + Assert.assertEquals(8192, received.position()); + Assert.assertEquals(TransformationResult.END_OF_FRAME , tr); + } + + + /* + * Minimal implementation to enable other transformations to be tested. It + * is NOT robust. */ private static class TesterTransformation implements Transformation { + + final ByteBuffer data; + + TesterTransformation() { + this(null); + } + + TesterTransformation(ByteBuffer data) { + this.data = data; + } + @Override public boolean validateRsvBits(int i) { return false; @@ -82,7 +135,11 @@ public class TestPerMessageDeflate { @Override public TransformationResult getMoreData(byte opCode, boolean fin, int rsv, ByteBuffer dest) throws IOException { - return null; + if (data == null) { + return TransformationResult.UNDERFLOW; + } + dest.put(data); + return TransformationResult.END_OF_FRAME; } @Override public Extension getExtensionResponse() { diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml index c07a701..bf43b67 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -160,6 +160,16 @@ </scode> </changelog> </subsection> + <subsection name="WebSocket"> + <changelog> + <fix> + <bug>65317</bug>: When using <code>permessage-deflate</code>, the + WebSocket connection was incorrectly closed if the uncompressed payload + size was an exact multiple of 8192. Based on a patch provided by Saksham + Verma. (markt) + </fix> + </changelog> + </subsection> <subsection name="Web applications"> <changelog> <fix> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org