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 c2fe7be Fix BZ 65317. Fix permessage-deflate with payloads of n*8192
bytes
c2fe7be is described below
commit c2fe7beb4b6e1473801b385425e240f4b0ed707a
Author: Mark Thomas <[email protected]>
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 129dda5..52a3066 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: [email protected]
For additional commands, e-mail: [email protected]