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

Reply via email to