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 cf4f6da  Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63913 Wrap 
NPEs
cf4f6da is described below

commit cf4f6da8cf1a7232e8081261032a38cca97af407
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Nov 12 09:11:05 2019 +0000

    Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63913 Wrap NPEs
    
    Wrap any NullPointerExceptions throw by the Inflater or Deflater used by
    the PerMessageDeflate extension in an IOException so that the error can
    be caught and handled by the WebSocket error handling mechanism.
---
 .../tomcat/websocket/LocalStrings.properties       |  1 +
 .../apache/tomcat/websocket/PerMessageDeflate.java | 37 ++++++++++++++++------
 .../apache/tomcat/websocket/Transformation.java    |  5 ++-
 .../tomcat/websocket/WsRemoteEndpointImplBase.java |  7 +++-
 .../tomcat/websocket/TestPerMessageDeflate.java    |  2 +-
 webapps/docs/changelog.xml                         | 11 +++++++
 6 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/java/org/apache/tomcat/websocket/LocalStrings.properties 
b/java/org/apache/tomcat/websocket/LocalStrings.properties
index 4f6f3b7..744619a 100644
--- a/java/org/apache/tomcat/websocket/LocalStrings.properties
+++ b/java/org/apache/tomcat/websocket/LocalStrings.properties
@@ -35,6 +35,7 @@ caseInsensitiveKeyMap.nullKey=Null keys are not permitted
 
 futureToSendHandler.timeout=Operation timed out after waiting [{0}] [{1}] to 
complete
 
+perMessageDeflate.alreadyClosed=The transformer has been closed and may no 
longer be used
 perMessageDeflate.deflateFailed=Failed to decompress a compressed WebSocket 
frame
 perMessageDeflate.duplicateParameter=Duplicate definition of the [{0}] 
extension parameter
 perMessageDeflate.invalidState=Invalid state
diff --git a/java/org/apache/tomcat/websocket/PerMessageDeflate.java 
b/java/org/apache/tomcat/websocket/PerMessageDeflate.java
index 90931c5..afcfcf0 100644
--- a/java/org/apache/tomcat/websocket/PerMessageDeflate.java
+++ b/java/org/apache/tomcat/websocket/PerMessageDeflate.java
@@ -204,6 +204,8 @@ public class PerMessageDeflate implements Transformation {
                         dest.array(), dest.arrayOffset() + dest.position(), 
dest.remaining());
             } catch (DataFormatException e) {
                 throw new 
IOException(sm.getString("perMessageDeflate.deflateFailed"), e);
+            } catch (NullPointerException e) {
+                throw new 
IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
             }
             dest.position(dest.position() + written);
 
@@ -229,7 +231,11 @@ public class PerMessageDeflate implements Transformation {
             } else if (written == 0) {
                 if (fin && (isServer && !clientContextTakeover ||
                         !isServer && !serverContextTakeover)) {
-                    inflater.reset();
+                    try {
+                        inflater.reset();
+                    } catch (NullPointerException e) {
+                        throw new 
IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
+                    }
                 }
                 return TransformationResult.END_OF_FRAME;
             }
@@ -314,7 +320,7 @@ public class PerMessageDeflate implements Transformation {
 
 
     @Override
-    public List<MessagePart> sendMessagePart(List<MessagePart> 
uncompressedParts) {
+    public List<MessagePart> sendMessagePart(List<MessagePart> 
uncompressedParts) throws IOException {
         List<MessagePart> allCompressedParts = new ArrayList<>();
 
         for (MessagePart uncompressedPart : uncompressedParts) {
@@ -345,10 +351,14 @@ public class PerMessageDeflate implements Transformation {
                 while (deflateRequired) {
                     ByteBuffer compressedPayload = writeBuffer;
 
-                    int written = deflater.deflate(compressedPayload.array(),
-                            compressedPayload.arrayOffset() + 
compressedPayload.position(),
-                            compressedPayload.remaining(), flush);
-                    compressedPayload.position(compressedPayload.position() + 
written);
+                    try {
+                        int written = 
deflater.deflate(compressedPayload.array(),
+                                compressedPayload.arrayOffset() + 
compressedPayload.position(),
+                                compressedPayload.remaining(), flush);
+                        
compressedPayload.position(compressedPayload.position() + written);
+                    } catch (NullPointerException e) {
+                        throw new 
IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
+                    }
 
                     if (!uncompressedPart.isFin() && 
compressedPayload.hasRemaining() && deflater.needsInput()) {
                         // This message part has been fully processed by the
@@ -401,7 +411,12 @@ public class PerMessageDeflate implements Transformation {
                         // - in middle of EOM bytes
                         // - about to write EOM bytes
                         // - more data to write
-                        int eomBufferWritten = deflater.deflate(EOM_BUFFER, 0, 
EOM_BUFFER.length, Deflater.SYNC_FLUSH);
+                        int eomBufferWritten;
+                        try {
+                            eomBufferWritten = deflater.deflate(EOM_BUFFER, 0, 
EOM_BUFFER.length, Deflater.SYNC_FLUSH);
+                        } catch (NullPointerException e) {
+                            throw new 
IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
+                        }
                         if (eomBufferWritten < EOM_BUFFER.length) {
                             // EOM has just been completed
                             compressedPayload.limit(compressedPayload.limit() 
- EOM_BYTES.length + eomBufferWritten);
@@ -447,11 +462,15 @@ public class PerMessageDeflate implements Transformation {
     }
 
 
-    private void startNewMessage() {
+    private void startNewMessage() throws IOException {
         firstCompressedFrameWritten = false;
         emptyMessage = true;
         if (isServer && !serverContextTakeover || !isServer && 
!clientContextTakeover) {
-            deflater.reset();
+            try {
+                deflater.reset();
+            } catch (NullPointerException e) {
+                throw new 
IOException(sm.getString("perMessageDeflate.alreadyClosed"), e);
+            }
         }
     }
 
diff --git a/java/org/apache/tomcat/websocket/Transformation.java 
b/java/org/apache/tomcat/websocket/Transformation.java
index 5186181..14d8093 100644
--- a/java/org/apache/tomcat/websocket/Transformation.java
+++ b/java/org/apache/tomcat/websocket/Transformation.java
@@ -101,8 +101,11 @@ public interface Transformation {
      * @return  The list of messages after this any any subsequent
      *          transformations have been applied. The size of the returned 
list
      *          may be bigger or smaller than the size of the input list
+     *
+     * @throws IOException If an error occurs during the transformation of the
+     *                     message parts
      */
-    List<MessagePart> sendMessagePart(List<MessagePart> messageParts);
+    List<MessagePart> sendMessagePart(List<MessagePart> messageParts) throws 
IOException;
 
     /**
      * Clean-up any resources that were used by the transformation.
diff --git a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java 
b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
index de6bf72..f022132 100644
--- a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
+++ b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
@@ -338,7 +338,12 @@ public abstract class WsRemoteEndpointImplBase implements 
RemoteEndpoint {
                 intermediateMessageHandler,
                 new EndMessageHandler(this, handler), -1));
 
-        messageParts = transformation.sendMessagePart(messageParts);
+        try {
+            messageParts = transformation.sendMessagePart(messageParts);
+        } catch (IOException ioe) {
+            handler.onResult(new SendResult(ioe));
+            return;
+        }
 
         // Some extensions/transformations may buffer messages so it is 
possible
         // that no message parts will be returned. If this is the case the
diff --git a/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java 
b/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java
index 7d883e1..9139460 100644
--- a/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java
+++ b/test/org/apache/tomcat/websocket/TestPerMessageDeflate.java
@@ -34,7 +34,7 @@ public class TestPerMessageDeflate {
      * https://bz.apache.org/bugzilla/show_bug.cgi?id=61491
      */
     @Test
-    public void testSendEmptyMessagePartWithContextTakeover() {
+    public void testSendEmptyMessagePartWithContextTakeover() throws 
IOException {
 
         // Set up the extension using defaults
         List<Parameter> parameters = Collections.emptyList();
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index a127cf8..9d99328 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -151,6 +151,17 @@
       </fix>
     </changelog>
   </subsection>
+  <subsection name="WebSocket">
+    <changelog>
+      <fix>
+        <bug>63913</bug>: Wrap any <code>NullPointerException</code>s throw by
+        the <code>Inflater</code> or <code>Deflater</code> used by the
+        <code>PerMessageDeflate</code> extension in an <code>IOException</code>
+        so that the error can be caught and handled by the WebSocket error
+        handling mechanism. (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