Uploaded image for project: 'ActiveMQ Classic'
  1. ActiveMQ Classic
  2. AMQ-5381

ActiveMQBytesMessage mishandles restoration of old message contents

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Major
    • Resolution: Fixed
    • 5.9.1, 5.10.0
    • 5.10.1, 5.11.0
    • JMS client

    Description

      Changes made in ActiveMQ 5.9.1, AMQ-4887, [cb5c29d02d02dc7f7fa4f5c1a97bd2a59078bccd introduced a bug in ActiveMQBytesMessage which results in a java.util.zip.ZipException: incorrect header check being thrown at org.apache.activemq.command.ActiveMQBytesMessage.restoreOldContent(ActiveMQBytesMessage.java:883) when a consumer attempts to reuse a received ActiveMQBytesMessage.

      This bug is triggered under a unique set of circumstances:

      1. A message is published by a JMS client with compression disabled on its ActiveMQConnection
      2. The message is consumed by a JMS client with compression enabled on its ActiveMQConnection
      3. The JMS consumer makes the received message writable in order to modify and reuse it:
        message.setReadOnlyProperties(false);
        message.setReadOnlyBody(false);
        
      4. The JMS consumer modifies the message, triggering a call to ActiveMQBytesMessage.initializeWriting()

      The problem within ActiveMQBytesMessage.initializeWriting() is that the method determines whether the message should be compressed when it is published (based on its current connection) BEFORE it has restored the message's original content. In the example above, the message's original compressed flag is changed from false to true, resulting in restoreOldContent() trying to decompress message contents which were never compressed.

      private void initializeWriting() throws JMSException {
              checkReadOnlyBody();
              if (this.dataOut == null) {
                  this.bytesOut = new ByteArrayOutputStream();
                  OutputStream os = bytesOut;
                  this.dataOut = new DataOutputStream(os);
              }
      
              // should compression be used when publishing this message??
              ActiveMQConnection connection = getConnection();
              if (connection != null && connection.isUseCompression()) {
                  compressed = true;
              }
      
              // restore the message's old content
              restoreOldContent();
      }
      

      A simple solution would be to move the restoreOldContent() method call before the connection.isUseCompression() conditional in ActiveMQBytesMessage.initializeWriting().

      Had a chance to look into this problem further. The best fix would be to only set the 'compressed' flag when the message's 'contents' are stored, instead of whenever the message is initialized for writing.

      Attachments

        Activity

          People

            tabish Timothy A. Bish
            brianjohnson Brian D. Johnson
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: